标签:col scan stack 网络 sum bool out ons ++
一眼题,要跑强连通分量
那就乖乖的打一边tarjan了,然后该怎么办呢
记录缩点后的图,并记录这个图上每个点的入度和出度
因为,如果一个点入度为零,那么就说明没有任何点跟他连接,则必须把它当成母点
反之如果出度为零,证明这个点没有办法跑出去,那么就需要当成母点,记录即可
比较答案即可
#include<bits/stdc++.h> using namespace std; const int N=1e6+7; const int M=5e7+6; int m,n,k,cnt,ans; int dfn[N],low[N],head[N],del[N],tot,color[N],sum[N],num,in[N],out[N],inc; struct edge { int nx,to; } e[M]; void add_edge(int a,int b) { cnt++;e[cnt].nx=head[a];e[cnt].to=b;head[a]=cnt; } bool vis[N]; stack<int> s; void paint(int x) { s.pop(); color[x]=num; sum[num]++; vis[x]=false; } void tarjan(int x) { dfn[x]=low[x]=++tot; vis[x]=true;s.push(x); for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } else if (vis[y]) low[x]=min(low[x],dfn[y]); } if (dfn[x]==low[x]) { num++; while (s.top()!=x) { int t=s.top(); paint(t); } paint(x); } } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { while (true) { int x; scanf("%d",&x); if (x==0) break; add_edge(i,x); } } for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i); for (int i=1;i<=n;i++) for (int j=head[i];j;j=e[j].nx) { int y=e[j].to; if (color[i]==color[y]) continue; in[color[y]]++; out[color[i]]++; } for (int i=1;i<=num;i++) if (!in[i]) ans++; for (int i=1;i<=num;i++) if (!out[i]) inc++; printf("%d\n",ans); if (num==1) printf("%d",0); else printf("%d",max(ans,inc)); return 0; }
标签:col scan stack 网络 sum bool out ons ++
原文地址:https://www.cnblogs.com/Hale522520/p/10628390.html