hdu4635Strongly connected

http://acm.hdu.edu.cn/showproblem.php?pid=4635

tarjan缩点 统计缩点后每个结点的出度入度 将那个包含原来点数最少的 且出度或者入度为0的大节点看作一个整体内部连边n*(n-1)个 连全部的; 其它的点为一整体连全部的 再两者连一同向的边 保证它的出度或者入度依旧为0的情况下任意连 最后减去原来的边M

  1 #include <iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<stdlib.h>
  5 #include<stack>
  6 using namespace std;
  7 #define N 100010
  8 #define M 100010
  9 #define INF 0xfffffff
 10 int a[110][110];
 11 stack<int>s;
 12 struct node
 13 {
 14     int u,v,next;
 15 }ed[M*2];
 16 int scc,sccno[N],head[N],lowlink[N],pre[N],dep,num[N],x[M],y[M],din[N],dout[N],o;
 17 void init()
 18 {
 19     o = 0;
 20     memset(head,-1,sizeof(head));
 21 }
 22 void add(int u,int v)
 23 {
 24     ed[o].u = u;
 25     ed[o].v = v;
 26     ed[o].next = head[u];
 27     head[u] = o++;
 28 }
 29 void dfs(int u)
 30 {
 31     int i;
 32     lowlink[u] = pre[u] = ++dep;
 33     s.push(u);
 34     for( i = head[u] ; i != -1 ; i = ed[i].next)
 35     {
 36         int v = ed[i].v;
 37         if(!pre[v])
 38         {
 39             dfs(v);
 40             lowlink[u] = min(lowlink[u],lowlink[v]);
 41         }
 42         else if(!sccno[v])
 43         lowlink[u] = min(lowlink[u],pre[v]);
 44     }
 45     if(lowlink[u]==pre[u])
 46     {
 47         scc++;
 48         for(;;)
 49         {
 50             int x = s.top();
 51             s.pop();
 52             sccno[x] = scc;
 53             if(x==u) break;
 54         }
 55     }
 56 }
 57 void find_scc(int n)
 58 {
 59     for(int i = 1; i <= n ;i++)
 60     if(!pre[i])
 61     dfs(i);
 62 }
 63 int main()
 64 {
 65     int i,t,n,m,a,b,kk=0;
 66     cin>>t;
 67     while(t--)
 68     {
 69         init();kk++;
 70         memset(num,0,sizeof(num));
 71         memset(pre,0,sizeof(pre));
 72         memset(din,0,sizeof(din));
 73         memset(dout,0,sizeof(dout));
 74         memset(sccno,0,sizeof(sccno));
 75         scanf("%d%d",&n,&m);
 76         for(i = 1; i <= m ; i++)
 77         {
 78             scanf("%d%d",&a,&b);
 79             x[i] = a;y[i] = b;
 80             add(a,b);
 81         }
 82         scc=0;dep=0;
 83         find_scc(n);
 84         printf("Case %d: ",kk);
 85         if(scc==1)
 86         {
 87             cout<<"-1
";
 88             continue;
 89         }
 90         for(i = 1; i <= n ; i++)
 91         num[sccno[i]]++;
 92         for(i = 1; i <= m ;i++)
 93         {
 94             if(sccno[x[i]]!=sccno[y[i]])
 95             {
 96                 dout[sccno[x[i]]]++;
 97                 din[sccno[y[i]]]++;
 98             }
 99         }
100         long long minz = INF;
101         for(i = 1 ;i <= scc ; i++)
102         if(minz>num[i]&&(din[i]==0||dout[i]==0))
103         minz = num[i];
104         long long ss=0;
105         ss = minz*(minz-1)+(n-minz)*(n-minz-1)+minz*(n-minz);
106         cout<<ss-m<<endl;
107     }
108     return 0;
109 }
View Code
原文地址:https://www.cnblogs.com/shangyu/p/3232045.html