Tarjan+缩点【强连通分量】【模板】

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<stack>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn=100005;//边数 
 9 const int maxn1=1005;//顶点数 
10 struct edge{
11     int from;
12     int to;
13     int next;
14 }EDGE[maxn];
15 vector<int>vc[maxn1];
16 int head[maxn1],dfn[maxn1],vis[maxn1],low[maxn1],col[maxn1],out[maxn1],in[maxn1],en[maxn1],stk[maxn1];//各个变量的意义可参照上篇博客
17 int edge_cnt=0,tot1=0,tot2=0,scc_cnt=0,tot0=0;
18 void add(int x,int y)
19 {
20     EDGE[edge_cnt].from=x;    
21     EDGE[edge_cnt].to=y;
22     EDGE[edge_cnt].next=head[x];
23     head[x]=edge_cnt++;
24 }
25 void Tarjan(int u)
26 {
27     low[u]=dfn[u]=++tot1;//注意tot1的初值必须是1【因为dfn必须为正数】,所以这里使用++tot1而不用tot1++;
28     vis[u]=1;
29     stk[++tot2]=u;
30     for(int i = head[u]; i != -1  ; i = EDGE[i].next)
31     {
32         if(!dfn[EDGE[i].to]){
33             Tarjan(EDGE[i].to);
34             low[u]=min(low[u],low[EDGE[i].to]);
35         }
36         else if(vis[EDGE[i].to]){
37             low[u]=min(low[u],low[EDGE[i].to]);
38         }
39     }
40             if(low[u]==dfn[u]){
41             int xx;
42             scc_cnt++;//注意scc_cnt也是从1开始的,因为要染色,区别于为染色的0 
43             do{
44                 xx=stk[tot2--];
45                 vc[scc_cnt].push_back(xx);
46                 col[xx]=scc_cnt;
47                 vis[xx]=0;
48             }while(xx!=u);
49         }
50 }
51 void INIT()
52 {
53     for(int i = 0 ; i < maxn1 ; i++)
54     vc[i].clear();
55     edge_cnt=0,tot1=0,tot2=0,scc_cnt=0,tot0=0;
56     memset(head,-1,sizeof(head));
57     memset(stk,0,sizeof(stk));
58     memset(in,0,sizeof(in));
59     memset(out,0,sizeof(out));
60     memset(dfn,0,sizeof(dfn));
61     memset(low,0,sizeof(low));
62     memset(col,0,sizeof(col));     
63  } 
64  void suodian()//缩点
65  {
66      for(int i = 0 ; i < edge_cnt ; i++)
67     {
68         if(col[EDGE[i].from]!=col[EDGE[i].to])
69         {
70             in[col[EDGE[i].to]]++;//缩点
71                out[col[EDGE[i].from]]++;
72         }
73     }    
74   } 
75 int main()
76 {
77     int n,m;
78     scanf("%d%d",&n,&m);
79     INIT();
80     while(m--)
81     {
82         int a,b;
83         scanf("%d%d",&a,&b);
84         add(a,b);
85     }
86     for(int i = 1 ; i <= n; i++)
87     {
88         if(!dfn[i])Tarjan(i);
89     }
90     suodian();
91     return 0;
92 }
93 /*4 5
94 1 3
95 2 4
96 4 2
97 1 4
98 2 1*/

 

posted @ 2018-05-03 19:36  MekakuCityActor  阅读(139)  评论(0编辑  收藏  举报