UVALive-4287 Proving Equivalences 有向图的强连通分量+缩点

时间:2021-06-05 09:47:22

题意:有n个命题,已知其中的m个推导,要证明n个命题全部等价(等价具有传递性),最少还需要做出几次推导。

思路:由已知的推导可以建一张无向图,则问题变成了最少需要增加几条边能使图变成强连通图。找出所有的强连通分量,将每一个连通分量视作一个大节点,则整张图变成了一张DAG。设出度为0的大节点个数为b,入度为0的大节点个数为a,则答案就是max(a,b)。

UVALive-4287 Proving Equivalences 有向图的强连通分量+缩点UVALive-4287 Proving Equivalences 有向图的强连通分量+缩点
  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstdio>
  6 #include<set>
  7 #include<map>
  8 #include<vector>
  9 #include<cstring>
 10 #include<stack>
 11 #include<cmath>
 12 #include<queue>
 13 #define clc(a,b) memset(a,b,sizeof(a))
 14 #include <bits/stdc++.h>
 15 using namespace std;
 16 #define LL long long
 17 const int maxn = 20005;
 18 const int inf=0x3f3f3f3f;
 19 const double pi=acos(-1);
 20 int  in[maxn],out[maxn];
 21 vector<int>G[maxn];
 22 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
 23 stack<int>S;
 24 
 25 void dfs(int u)
 26 {
 27     pre[u]=lowlink[u]=++dfs_clock;
 28     S.push(u);
 29     for(int i=0; i<G[u].size(); i++)
 30     {
 31         int v=G[u][i];
 32         if(!pre[v])
 33         {
 34             dfs(v);
 35             lowlink[u]=min(lowlink[u],lowlink[v]);
 36         }
 37         else if(!sccno[v])
 38         {
 39             lowlink[u]=min(lowlink[u],pre[v]);
 40         }
 41     }
 42     if(lowlink[u]==pre[u])
 43     {
 44         scc_cnt++;
 45         for(;;)
 46         {
 47             int x=S.top();
 48             S.pop();
 49             sccno[x]=scc_cnt;
 50             if(x==u)
 51                 break;
 52         }
 53     }
 54 }
 55 
 56 void find_scc(int n)
 57 {
 58     dfs_clock=scc_cnt=0;
 59     clc(sccno,0);
 60     clc(pre,0);
 61     for(int i=0; i<n; i++)
 62         if(!pre[i])
 63             dfs(i);
 64 }
 65 
 66 int main()
 67 {
 68     int t,n,m;
 69     scanf("%d",&t);
 70     while(t--)
 71     {
 72         scanf("%d%d",&n,&m);
 73         for(int i=0; i<n; i++)
 74             G[i].clear();
 75         for(int i=0; i<m; i++)
 76         {
 77             int u,v;
 78             scanf("%d%d",&u,&v);
 79             u--;
 80             v--;
 81             G[u].push_back(v);
 82         }
 83         find_scc(n);
 84         for(int i=1; i<=scc_cnt; i++)
 85             in[i]=out[i]=0;
 86         for(int u=0; u<n; u++)
 87         {
 88             for(int i=0; i<G[u].size(); i++)
 89             {
 90                 int v=G[u][i];
 91                 if(sccno[u]!=sccno[v])
 92                     in[sccno[v]]=out[sccno[u]]=1;
 93             }
 94         }
 95         int a=0,b=0;
 96         for(int i=1; i<=scc_cnt; i++)
 97         {
 98             if(!in[i])
 99                 a++;
100             if(!out[i])
101                 b++;
102         }
103         int ans=max(a,b);
104         if(scc_cnt==1)
105             ans=0;
106         printf("%d\n",ans);
107     }
108     return 0;
109 }
View Code