codevs1506传话(kosaraju算法)

- -   - -   - -   - -

一个()打成[] 看了一晚上.....

/*
求强连通分量 kosaraju算法 边表存图 正反构造两个图 跑两边 分别记下入栈顺序 和每个强连通分量的具体信息 */ #include<iostream> #include<cstring> #include<cstdio> #include<stack> #define maxn 1010 #define maxx 10010 using namespace std; int n,m,num,head1[maxn],head2[maxn],f[maxn],cnt; int flag[maxn],ans[maxn][maxn]; stack<int>s; struct node { int u,v,per; }e1[maxx],e2[maxx]; void Input()//输入 构图 e1为正 e2为反 { int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) { cin>>x>>y; num++; e1[num].u=x; e1[num].v=y; e1[num].per=head1[x]; head1[x]=num; e2[num].u=y; e2[num].v=x; e2[num].per=head2[y]; head2[y]=num; } } void Dfs1(int k) { f[k]=1; for(int p=head1[k];p;p=e1[p].per) { if(!f[e1[p].v]) Dfs1(e1[p].v); } s.push(k);//记录入栈顺序 } void Dfs2(int k) { f[k]=1; ans[cnt][++ans[cnt][0]]=k;//记下第cnt个强连通分量的每个点 for(int i=head2[k];i;i=e2[i].per) if(f[e2[i].v]==0) Dfs2(e2[i].v); if(ans[cnt][0]>1)flag[k]=1;//如果第 cnt个强连通分量的大小>1 则x属于某个强连通分量 } void Kosaraju() { memset(f,0,sizeof(f)); for(int i=1;i<=n;i++)//跑第一遍Dfs 每个点依次入栈 { if(f[i]==0) Dfs1(i); } memset(f,0,sizeof(f)); while(!s.empty())//跑第二遍Dfs 标记每个点是否属于一个强连通分量 并计算数量 { int tmp=s.top(); s.pop(); if(f[tmp]==0) { cnt++;//计数强连通分量 Dfs2(tmp); } } } void Printf() { for(int i=1;i<=n;i++) if(flag[i]==1)cout<<"T"<<endl; else cout<<"F"<<endl; } int main() { Input(); Kosaraju(); Printf(); return 0; }

 

posted @ 2016-04-18 21:46  一入OI深似海  阅读(216)  评论(0编辑  收藏  举报