tarjan求强连通分量 + 缩点 + 求割点割边

强连通分量:

       引用度娘:“有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。”

       就是在一幅图里,任意两点可以相互到达,这一幅图就是一个强连通分量。

       

       这幅图中强连通分量有三个,为:1-2-3、4、5 。

强连通分量的应用:

       1、缩点。 

       2、求割点和割边的数量。

代码:

tarjan 模版 + 缩点

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define MOD 998244353 
 4 #define INF 0x3f3f3f3f
 5 #define mem(a,x) memset(a,x,sizeof(a))  
 6 using namespace std;
 7 int dfn[50005];
 8 int low[50005];
 9 int vis[50005];
10 int stacks[50005];
11 int color[50005];
12 int cnt[50005];
13 int deep,sum,top;
14 int n,m;
15 vector<int>g[50005];
16 void tarjan(int u)
17 {
18    dfn[u]=++deep;
19    low[u]=deep;
20    vis[u]=1;
21    stacks[++top]=u;
22    for(int i=0;i<g[u].size();i++){
23        int v=g[u][i];
24        if(!dfn[v])
25        {
26           tarjan(v);
27           low[u]=min(low[u],low[v]);
28        }else{
29            if(vis[v]){
30               low[u]=min(low[v],low[u]);
31            }
32        }
33    }
34    if(dfn[u]==low[u])
35    {
36       color[u]=++sum;
37       vis[u]=0;
38       while(stacks[top]!=u)
39       {
40           color[stacks[top]]=sum;
41           vis[stacks[top--]]=0;
42       }
43       top--;
44    }
45 }
46 int main()
47 {
48     deep=0;
49     top=0;
50     sum=0;
51     mem(dfn,0);
52     mem(vis,0);
53     mem(cnt,0);
54     scanf("%d %d",&n,&m);
55     while(m--){
56        int from,to;
57        scanf("%d %d",&from,&to);
58        g[from].push_back(to);
59     }
60     for(int i=1;i<=n;i++){
61         if(!dfn[i]){
62            tarjan(i);
63         }
64     }
65     int num=0;
66     for(int i=1;i<=n;i++){
67         cnt[color[i]]++;
68     }
69     for(int i=1;i<=sum;i++){
70       if(cnt[i]>1)num++;
71     }
72     cout<<num;
73     return 0;
74 }

 

tarjan 求割点

在原来的tarjan 基础上 加一个特判:如果一个点的为根节点且这个点有两个及以上的儿子,这个点就是割点。

代码:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define MOD 998244353 
 4 #define INF 0x3f3f3f3f
 5 #define mem(a,x) memset(a,x,sizeof(a))  
 6 using namespace std;
 7 int n,m;
 8 int deep=0,root;
 9 vector<int>g[200015];
10 int dfn[100015];
11 int low[100015];
12 int stack[100015];
13 int vis[100015];
14 int iscut[100015];
15 int tarjan(int u,int fa)
16 {
17     int child=0,lowu;
18     lowu=dfn[u]=++deep;
19     int sz=g[u].size();
20     for(int i=0;i<sz;i++)
21     {
22         int v=g[u][i];
23         if(!dfn[v])
24         {
25             int v=g[u][i];
26             int lowv=tarjan(v,u);
27             lowu=min(lowu,lowv);
28             if(lowv>dfn[u])
29             {
30                 iscut[u]=1;
31             }
32         }else{
33             if(v!=fa&&dfn[v]<dfn[u])
34             {
35                 lowu=min(lowu,dfn[v]);
36             }
37         }
38     }
39     if(fa<0&&child==1)
40     {
41         iscut[u]=0;
42     }
43     low[u]=lowu;
44     return lowu;
45 }
46 int main()
47 {
48      scanf("%d %d",&n,&m);
49      for(int i=1;i<=m;i++){
50          int from,to;
51          scanf("%d %d",&from,&to);
52          g[from].push_back(to);
53          g[to].push_back(from);
54      }
55      for(int i=1;i<=n;i++){
56          if(!vis[i]){
57            root=i;
58            tarjan(i,-1);
59          }
60      }
61      int ans=0;
62      for(int i=1;i<=n;i++){
63          if(iscut[i]){
64              ans++;
65          }
66      }
67      printf("%d\n",ans);
68      for(int i=1;i<=n;i++){
69          if(iscut[i]){
70              printf("%d ",i);
71          }
72      }
73      return 0;
74 }

求割边

 1 #include<cstdio> 
 2 #include<vector>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #define hi printf("hi!");
 7 using namespace std;
 8 
 9 vector<pair<int,int> >bridge;
10 vector<int> g[10010];
11 int dfn[10010],low[10010];
12 int deep,root,n,m,ans;
13 
14 int tarjan(int u,int fa)
15 {
16     int lowu;
17     lowu=dfn[u]=++deep;
18     int sz=g[u].size();
19     for(int i=0;i<sz;i++)
20     {
21         int v=g[u][i];
22         if(!dfn[v])
23         {
24             int lowv=tarjan(v,u);
25             lowu=min(lowu,lowv);
26             if(lowv>dfn[u])
27             {
28                 int from,to;
29                 from=u;
30                 to=v;
31                 if(from>to)
32                 {
33                     swap(from,to);
34                 }
35                 bridge.push_back(make_pair(from,to));
36             }
37         }
38         else
39         {
40             if(v!=fa&&dfn[v]<dfn[u])
41             {
42                 lowu=min(lowu,dfn[v]);
43             }
44         } 
45     }
46     low[u]=lowu;
47     return lowu;
48 } 
49 
50 int main()
51 {
52     scanf("%d%d",&n,&m);
53     for(int i=1;i<=m;i++)
54     {
55         int from,to;
56         scanf("%d%d",&from,&to);
57         g[from].push_back(to);
58         g[to].push_back(from);
59     }
60     for(int i=1;i<=n;i++)
61     {
62         if(!dfn[i])
63         {
64             root=i;
65             tarjan(i,-1);
66         }
67     }
68     for(int i=0;i<bridge.size();i++)
69     {
70         printf("%d %d\n",bridge[i].first,bridge[i].second);
71     }
72 }

 

posted @ 2020-08-25 21:26  hachuochuo  阅读(135)  评论(0编辑  收藏  举报