Proving Equivalences HDU-2767 (tarjan缩点)

Practice link:  HDU-2767

题意:给你一张有向图,问你最少需要增加几条边整张图变成一个强连通分量。

思路:首先我们把整张图已有的边来找到现有的图有的强连通分量,然后进行缩点,然后去得到每个强连通分量的入度和出度,要让整张图联通,只需要让所有强连通分量连成一个环即可,因此考虑 max( 入度为0的点 ,出度为0的点)即可。

         注意点是当现有图只有一个强连通分量是,直接输出0。

代码:

  1 //#include<bits/stdc++.h>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<string>
  7 #include<vector>
  8 #include<stack>
  9 #include<bitset>
 10 #include<cstdlib>
 11 #include<cmath>
 12 #include<set>
 13 #include<list>
 14 #include<deque>
 15 #include<map>
 16 #include<queue>
 17 #define ll long long
 18 #define MOD 1000000007
 19 #define INF 0x3f3f3f3f
 20 #define mem(a,x) memset(a,x,sizeof(a))
 21 #define lowbit(x) x&(-x)
 22 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 23 using namespace std;
 24 int dfn[50005];
 25 int low[50005];
 26 int vis[50005];
 27 int stacks[50005];
 28 int color[50005];
 29 int cnt[50005];
 30 int deep,sum,top;
 31 int n,m;
 32 vector<int>g[50005];
 33 void tarjan(int u)
 34 {
 35    dfn[u]=++deep;
 36    low[u]=deep;
 37    vis[u]=1;
 38    stacks[++top]=u;
 39    for(int i=0;i<g[u].size();i++){
 40        int v=g[u][i];
 41        if(!dfn[v])
 42        {
 43           tarjan(v);
 44           low[u]=min(low[u],low[v]);
 45        }else{
 46            if(vis[v]){
 47               low[u]=min(low[v],low[u]);
 48            }
 49        }
 50    }
 51    if(dfn[u]==low[u])
 52    {
 53       color[u]=++sum;
 54       vis[u]=0;
 55       while(stacks[top]!=u)
 56       {
 57           color[stacks[top]]=sum;
 58           vis[stacks[top--]]=0;
 59       }
 60       top--;
 61    }
 62 }
 63 //tarjan 部分
 64 int T;
 65 int in[20005],out[20005];
 66 int main()
 67 {
 68     int T;
 69     cin>>T;
 70     while(T--){
 71         deep=0;
 72         top=0;
 73         sum=0;
 74         scanf("%d %d",&n,&m);
 75         for(int i=0;i<=n;i++){
 76             g[i].clear();
 77             dfn[i]=0;
 78             vis[i]=0;
 79             cnt[i]=0;
 80             in[i]=0;
 81             out[i]=0;
 82         }
 83         for(int i=1;i<=m;i++){
 84             int from,to;
 85             scanf("%d %d",&from,&to);
 86             g[from].push_back(to);
 87         }
 88         for(int i=1;i<=n;i++){
 89             if(!dfn[i]){
 90                 tarjan(i);
 91             }
 92         }
 93         for(int i=1;i<=n;i++){
 94             for(auto v:g[i]){
 95                 if(color[i]!=color[v]){
 96                     out[color[i]]++;
 97                     in[color[v]]++;
 98                 }
 99             }
100         }
101         int temp1=0,temp2=0;
102         for(int i=1;i<=sum;i++){
103             if(in[i]==0)temp1++;
104             if(out[i]==0)temp2++;
105         }
106         if(sum==1){
107             printf("0\n");
108         }else{
109             printf("%d\n",max(temp1,temp2));
110         }
111         
112         
113     }
114     return 0;
115 }

 

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