题意:判断一个有向图是不是一个强连通分量,是的话输出“Yes”,不是的话输出“No”。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1269
——>>直接Tarjan。
#include <cstdio>
#include <vector>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn = 10000 + 10;
vector<int> G[maxn];
int scc_cnt, dfs_clock, pre[maxn], lowlink[maxn], sccno[maxn];
stack<int> st;
void dfs(int u)
{
lowlink[u] = pre[u] = ++dfs_clock;
st.push(u);
int d = G[u].size();
for(int i = 0; i < d; i++)
{
int v = G[u][i];
if(!pre[v])
{
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if(lowlink[u] == pre[u])
{
scc_cnt++;
for(;;)
{
int x = st.top();
st.pop();
sccno[x] = scc_cnt;
if(x == u) break;
}
}
}
void find_scc(int n)
{
dfs_clock = scc_cnt = 0;
memset(pre, 0, sizeof(pre));
memset(sccno, 0, sizeof(sccno));
for(int i = 1; i <= n; i++)
if(!pre[i]) dfs(i);
}
int main()
{
int N, M, i, A, B;
while(~scanf("%d%d", &N, &M))
{
if(!N && !M) return 0;
for(i = 1; i <= N; i++) G[i].clear();
for(i = 0; i < M; i++)
{
scanf("%d%d", &A, &B);
G[A].push_back(B);
}
find_scc(N);
if(scc_cnt == 1) printf("Yes\n");
else printf("No\n");
}
return 0;
}