题目链接
思路
tarjan求强连通分量模板题
代码
#include <bits/stdc++.h>
using namespace std;
int low[10005], dfn[10005], vis[10005], tot = 0, n, ans;
stack<int> st;
vector<int> e[10005];
void tarjan(int u)
{
dfn[u] = low[u] = ++tot;
vis[u] = 1;
st.push(u);
for(int i = 0; i < e[u].size(); ++i)
{
int v = e[u][i];
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(vis[v]) low[u] = min(low[u], dfn[v]);
/*
在求强连通分量时可以low[u] = min(low[u],low[v])
但是求无向图的割点/双连通分量时只能写low[u] = min(low[u],dfn[v])。
如割点,{代表环的点集}{123}{245}{567}这种图就会少计算,所以还是dfn稳
*/
}
if(dfn[u] == low[u])
{
++ans;
while(1)
{
int now = st.top();
st.pop();
vis[now] = 0;
if(now == u) break;
}
}
}
int main()
{
int n, m;
while(scanf("%d%d",&n,&m),n)
{
for(int i = 1; i <= n; ++i) e[i].clear(), vis[i] = low[i] = dfn[i] = 0;
tot = ans = 0;
while(m--)
{
int u, v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
}
for(int i = 1; i <= n; ++i)
if(!dfn[i]) tarjan(i);
printf("%s\n",ans==1?"Yes":"No");
}
return 0;
}