tarjan强连通分量,缩点

 1 #include
 2 using namespace std;
 3 int n,m;
 4 struct edge{
 5     int next,to;
 6 }e[1000];
 7 int tot;
 8 int first[10009];
 9 int dfn[10009];
10 int low[10009];
11 int ans;
12 int sum;
13 int sta[10009];
14 bool insta[10009]; 
15 int top;//表示栈顶位置 
16 int id[100009];//标记是哪一组的 
17 void add_edge(int a,int b)
18 {
19     tot++;
20     e[tot].next=first[a];
21     first[a]=tot;
22     e[tot].to=b;
23 }
24 void dfs(int now)
25 {
26     sum++;
27     low[now]=sum,dfn[now]=sum;
28     top++;
29     sta[top]=now,insta[now]=true;
30     for(int i=first[now];i;i=e[i].next)
31     {
32         if(dfn[e[i].to]==0)
33         {
34             dfs(e[i].to);
35             if(low[e[i].to]<low[now])
36             {
37                 low[now]=low[e[i].to];
38             }
39         }
40         else
41         {
42             if(insta[e[i].to]==true&&dfn[e[i].to]<low[now])
43             {
44                 low[now]=dfn[e[i].to];
45             }
46         }
47     }
48     if(low[now]==dfn[now])
49     {
50         ans++;
51         int p=sta[top];
52         while(p>now)
53         {
54             id[p]=ans;
55             insta[p]=false;
56             top--;
57             p=sta[top];
58         }
59         top--;
60         id[now]=ans;
61         insta[now]=false;
62     }
63 }
64 int main()
65 {
66     cin>>n>>m;
67     for(int i=1;i<=m;i++)
68     {
69         int a,b;
70         cin>>a>>b;
71         add_edge(a,b);
72     }
73     for(int i=1;i<=n;i++)
74     {
75         if(dfn[i]==0)dfs(i);
76     }
77     cout<endl;
78     for(int i=1;i<=n;i++)
79     {
80         printf("%d属于第%d个强连通分量\n",i,id[i]);
81     }
82 }

 

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 using namespace std;
 7 
 8 const int maxn = 10001;
 9 const int maxm = 10001;
10 int first[maxn],id[maxn];   //id[i]表示:i点所属强连通分量的编号 
11 int next[maxm],en[maxm];
12 int dfn[maxn],low[maxn],sta[maxn];
13 bool insta[maxn];
14 int tot=0,sign=0,top=0,n,m,a,b,sum=0,i;
15 
16 void Add(int x, int y)
17 {
18     tot++;
19     next[tot]=first[x];
20     first[x]=tot;
21     en[tot]=y;
22 }
23 
24 void dfs(int x)
25 {
26     int k,i;
27     sign++;
28     low[x]=sign; dfn[x]=sign;   //x根的时间戳,x的时间戳 
29     top++;
30     sta[top]=x; insta[x]=true;  //sta[top]表示栈顶;insta[x]=true 是x在栈中的标记 
31     k=first[x];                 //枚举从x出发的第一条边 
32     while(k!=0)                 //枚举从x出发的所有边 
33     {
34         i=en[k];                //对面顶点 
35         if(dfn[i]==0)           //时间戳为0,没有搜索过 
36         {
37             dfs(i);             //从i出发继续搜索 
38             if(low[i]//更新x的根的时间戳(缩小) 
39         }
40         else  //如果i搜索过 
41         {
42             if((insta[i]) && (dfn[i]//如果i还在栈中,更新x的根的时间戳(缩小) 
43         }
44         k=next[k];  //从x出发的下一条边 
45     }
46     if(low[x]==dfn[x])  //如果从x出发的所有边都枚举了,并且x根的时间戳就是自己的时间戳,说明x是一个强连通分量的根 
47     {
48         sum++;       //累加强连通分量数量 
49         i=sta[top];  //得到栈顶的顶点编号 
50         while(i!=x)  //依次出栈 
51         {
52             id[i]=sum;         //得到i点所属强连通分量 
53             insta[i]=false;    //出栈标记 
54             top--; 
55             i=sta[top];        //新的栈顶位置 
56         }
57         top--;                 //x出栈 
58         id[x]=sum;             //得到x点所属强连通分量   
59         insta[x]=false;        //出栈标记  
60     } 
61 }
62 
63 int main()
64 {
65     freopen("tarjan.in","r",stdin);
66     freopen("tarjan.out","w",stdout);
67     cin>>n>>m;
68     for(i=1;i<=m;i++) 
69     {
70         cin>>a>>b;
71         Add(a,b);
72     }
73 
74     memset(dfn,0,sizeof(dfn));
75     sum=0; sign=0;
76     for(i=1;i<=n;i++) 
77        if(dfn[i]==0) dfs(i);
78     
79     cout<//输出强联通的个数 
80     for(i=1;i<=n;i++) 
81         cout<" 属于第 "<" 个强连通分量"<<endl;
82     return 0;
83 }

 

你可能感兴趣的:(tarjan强连通分量,缩点)