首页 > 代码库 > 图的连通_Tarjan

图的连通_Tarjan

强连通分量

http://blog.csdn.net/xinghongduo/article/details/6195337
http://www.cnblogs.com/shadowland/p/5872257.html
http://blog.csdn.net/jeryjeryjery/article/details/52829142?locationNum=4&fps=1
https://www.byvoid.com/zht/blog/scc-tarjan/

 技术分享

题目

bzoj1051 缩点

被所有的牛认为受欢迎,也就意味着缩点之后,该牛所在的点的出度为0(否则其他点不可能全部通往该点)

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int Maxn=10000;
 6 const int Maxe=50000;
 7 int n,e,tot=0,num=0;
 8 int top;
 9 int Cnt[Maxn+50],Outdegree[Maxn+50];
10 int Low[Maxn+50],Dfn[Maxn+50],Fir[Maxe+50],Stack[Maxn+50],Belong[Maxn+50];
11 bool Vis[Maxn+50];
12 struct Edge{
13     int u,v,next;
14 }E[Maxe+50];
15 
16 int read(){
17     char ch=getchar();
18     int x=0,f=1;
19     while (ch<0||ch>9) {
20         if (ch==-) f=-1;
21         ch=getchar();        
22     }
23     while (ch>=0&&ch<=9){
24         x=x*10+ch-0;
25         ch=getchar();
26     }
27     return  x*f; 
28 }
29 void Insert(int x,int y){
30     tot++;
31     E[tot].u=x;
32     E[tot].v=y;
33     E[tot].next=Fir[x];
34     Fir[x]=tot;
35 }
36 void Tarjan(int u){
37     Low[u]=Dfn[u]=++tot;
38     Stack[++top]=u;
39     Vis[u]=1;
40     for (int p=Fir[u];p!=-1;p=E[p].next){
41         int v=E[p].v;
42         if (!Dfn[v]){
43             Tarjan(v);
44             Low[u]=min(Low[u],Low[v]);
45         }
46         else if (Vis[v])
47             Low[u]=min(Low[u],Dfn[v]);
48     }
49     if (Dfn[u]==Low[u]){
50         num++;
51         int v=-1;
52         while (u!=v){
53             v=Stack[top--];
54             Belong[v]=num;
55             Cnt[num]++;
56             Vis[v]=0;
57         }
58     }
59 }
60 int main(){
61     memset(Fir,-1,sizeof(Fir));
62     n=read();e=read();
63     for (int i=1;i<=e;i++){
64         int u=read(),v=read();
65         Insert(u,v);
66     }
67     memset(Low,0,sizeof(Low));
68     memset(Dfn,0,sizeof(Dfn));
69     memset(Vis,0,sizeof(Vis));
70     for (int i=1;i<=n;i++)
71       if (!Dfn[i])
72         Tarjan(i);
73     for (int i=1;i<=e;i++)
74       if (Belong[E[i].u]!=Belong[E[i].v])
75         Outdegree[Belong[E[i].u]]++;
76     int res=0,ans=0;
77     for (int i=1;i<=num;i++)
78       if (Outdegree[i]==0){
79           res++;
80           ans=i;
81       }
82     if(res==1) printf("%d\n",Cnt[ans]);
83     else printf("0\n");
84     return 0;
85 }
View Code

poj1236 缩点

题意+题解

第一问求缩点之后入度为0的点数(只要入度不为0,就可从其他点处得到软件);

第二问答案为max(入度为零的点数,出度为0的点数)

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int Maxn=100; 
 6 const int Maxe=10000;
 7 struct Edge{
 8     int from,u,v;
 9 }E[Maxe];
10 int n;
11 int tot_e=0,top=0,ans1,ans2,cnt=0;
12 int Fir[Maxn+50]={0},dfn[Maxn+50],low[Maxn+50],Stack[Maxn+100],Belong[Maxn+50];
13 int time=0;
14 int V[Maxn+50],Indegree[Maxn+50],Outdegree[Maxn+50];
15 int read(){
16     int x=0,f=1;
17     char ch=getchar();
18     while (ch<0||ch>9){
19         if (ch==-) f=-1;
20         ch=getchar();
21     }
22     while (ch>=0&&ch<=9){
23         x=x*10+ch-0;
24         ch=getchar();
25     }
26     return x*f;
27 }
28 void Insert(int u,int v){
29     tot_e++;
30     E[tot_e].u=u;E[tot_e].v=v;
31     E[tot_e].from=Fir[u];Fir[u]=tot_e;
32 }
33 void Tarjan(int x){
34     int y;
35     dfn[x]=low[x]=++time;
36     V[x]=1;
37     Stack[++top]=x;
38     for (int i=Fir[x];i;i=E[i].from){
39         y=E[i].v;
40         if (!V[y]){
41             Tarjan(y);
42             low[x]=min(low[x],low[y]);
43         }
44         if (V[y]==1)
45           low[x]=min(low[x],dfn[y]);
46     }
47     if (dfn[x]==low[x]){
48         cnt++;
49         do{
50             y=Stack[top--];
51             Belong[y]=cnt;V[y]=2;
52         }while (y!=x);
53     }
54 }
55 int main(){
56     n=read();
57     memset(V,0,sizeof(V));
58     for (int i=1;i<=n;i++){//build the graph
59         int j=read();
60         while(j){
61             Insert(i,j);
62             j=read();
63         }
64     }
65     for (int i=1;i<=n;i++)
66       if (!V[i])
67         Tarjan(i);
68     if (cnt==1){
69         printf("1\n0");
70         return 0;
71     }
72     for (int i=1;i<=tot_e;i++)
73       if (Belong[E[i].u]!=Belong[E[i].v]){
74           Outdegree[Belong[E[i].u]]++;
75           Indegree[Belong[E[i].v]]++;
76     }
77     ans1=ans2=0;
78     for (int i=1;i<=cnt;i++){
79       if (Indegree[i]==0) ans1++;
80       if (Outdegree[i]==0) ans2++;
81     }
82     printf("%d\n%d",ans1,max(ans1,ans2));
83     return 0;
84 }
View Code

poj3177 边双联通分量

题意+题解

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int Maxn=5000;
 6 const int Maxe=10000;
 7 struct edge{
 8     int u,v,from;
 9 }E[Maxe+100];
10 int n,e;
11 int tot=0,T=0,ccnum=0;
12 int Fir[Maxn+50],dfn[Maxn+50],low[Maxn+50],cc[Maxn+50],Degree[Maxn+50];
13 bool Is_cut[Maxn+50]={0};
14 int read(){
15     char ch=getchar();
16     int x=0,f=1;
17     while (ch<0||ch>9){
18         if (ch==-) f=-1;
19         ch=getchar();
20     }
21     while (ch>=0&&ch<=9){
22         x=x*10+ch-0;
23         ch=getchar();
24     }
25     return x*f;
26 }
27 void Insert(int x,int y){
28     tot++;
29     E[tot].u=x;E[tot].v=y;
30     E[tot].from=Fir[x];Fir[x]=tot;
31 }
32 void Tarjan(int x,int fa){
33     dfn[x]=low[x]=++T;
34     for (int i=Fir[x];i;i=E[i].from)
35       if (E[i].v!=fa){
36           int y=E[i].v;
37           if (!dfn[y]){
38               Tarjan(y,x);
39               low[x]=min(low[x],low[y]);
40               if (low[y]>dfn[x]) Is_cut[i]=1,Is_cut[i%2?i+1:i-1]=1;
41           }
42         else low[x]=min(low[x],dfn[y]);
43       }
44 }
45 void dfs(int x,int fa){
46     cc[x]=ccnum;
47     for (int i=Fir[x];i;i=E[i].from)
48       if (E[i].v!=fa&&!Is_cut[i]&&!cc[E[i].v])
49         dfs(E[i].v,x);
50 }
51 int main(){
52     n=read();e=read();
53     memset(Fir,0,sizeof(Fir));
54     for (int i=1;i<=e;i++){
55         int u=read(),v=read();
56         Insert(u,v);
57         Insert(v,u);
58     }
59     for (int i=1;i<=n;i++)
60       if (!dfn[i]) Tarjan(i,-1);
61     for (int i=1;i<=n;i++)
62       if (!cc[i]){
63         ccnum++;
64         dfs(i,-1);
65     }
66     int ans=0;
67     for (int i=1;i<=tot;i++)
68       if (cc[E[i].u]!=cc[E[i].v]){
69           Degree[cc[E[i].u]]++;
70           Degree[cc[E[i].v]]++; 
71       }
72     for (int i=1;i<=ccnum;i++)
73       if (Degree[i]==2)ans++;
74     printf("%d",(ans+1)/2);
75     return 0;
76     return 0;
77 }
View Code

 

图的连通_Tarjan