第一遍不太熟,第二遍飞快地打出来了
算是tarjan模板了吧,几天了也总算是有一点对tarjan求法过程的理解了。
if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]);//如果没有访问过u,则tarjan一下,如果u走出去搞到的low更小则用这个更新x的low
else if(ins[u])low[x] = min(low[x],dfn[u]);//如果u访问过但在栈里,那么u的low说不定已经被更新过了,如果此时令low[x]与low[u]取min,则回溯时作为祖先的u的low与dfn就不相等了欸在这道题里好像确实是等价的,可能在其他tarjan算法里不等价吧,那我还是不太知道为什么在这里与dfn[u]取min了。。。whatsapity..
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<queue> 7 8 using namespace std; 9 10 const int Maxn = 10010; 11 12 vector<int> g[Maxn],scc[Maxn]; 13 int stack[Maxn],ins[Maxn],inscc[Maxn]; 14 int dfn[Maxn],low[Maxn],oud[Maxn]; 15 int n,m,cntv,cntscc,top; 16 17 void tarjan(int x){ 18 low[x] = dfn[x] = ++cntv; 19 ins[x] = 1,stack[++top] = x; 20 for(int i = 0;i < g[x].size();i++){ 21 int u = g[x][i]; 22 if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]); 23 else if(ins[u])low[x] = min(low[x],dfn[u]); 24 } 25 if(dfn[x] == low[x]){ 26 int y = 0; cntscc++; 27 while(y != x){ 28 y = stack[top--]; 29 ins[y] = 0; 30 inscc[y] = cntscc; 31 scc[cntscc].push_back(y); 32 } 33 } 34 } 35 36 int main(){ 37 ios::sync_with_stdio(false); 38 cin >> n >> m; 39 for(int i = 1;i <= m;i++){ 40 int x,y; 41 cin >> x >> y; 42 g[x].push_back(y); 43 } 44 for(int i = 1;i <= n;i++)if(!dfn[i])tarjan(i); 45 for(int i = 1;i <= cntscc;i++){ 46 for(int j = 0;j < scc[i].size();j++){ 47 int u = scc[i][j]; 48 for(int k = 0;k < g[u].size();k++){ 49 int v = g[u][k]; 50 if(inscc[v] != i)oud[i]++; 51 } 52 } 53 } 54 int ans = 0; 55 for(int i = 1;i <= cntscc;i++)if(!oud[i]){ 56 if(ans){printf("0");return 0;} 57 ans = scc[i].size(); 58 } 59 cout << ans; 60 return 0; 61 }
原文地址:https://www.cnblogs.com/Wangsheng5/p/11651417.html
时间: 2024-10-10 18:12:49