HDU - 4635 Strongly connected

Strongly connected HDU - 4635 

题意:给你一个n个点m条边的有向简单图,问最多加多少边使得图还是一个简单图,并且整个图不是一个强连通,如果原先整个图就是个强连通,就输出-1。

首先要知道的是简单图,没有重边,而且没有自环,但是有其他的环。这样先不考虑整个图最终不是一个强连通,我们最多就可以加n*(n-1)-m,也是每个点向其他点连一条边,然后减去原来已经有的。

然后我们来考虑让整个图不是强连通,我们先把其他子强连通求出来这样缩点之后就是一棵树了。那我们原先要让它变成一个强连通的话,就是入度为零和出度为零的点互相连边,然后多出来的可以任意向其他点连边,

那现在不让它是强连通,并且要能加最多的边的话,我们就剩下一个入度为0或者出度为0的点不连即可。这样不连的边就是这个点向其他点连的边,也就是这个强连通里的点数*剩下的点数,所以我们需要统计下每个点(强连通)的大小,

这样就是找所有入度或者出度为0的点 大小*(n-大小)最小的那一个,然后减去便可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long ll;
 5 const int N=1e5+11;
 6 struct Side{
 7     int v,ne;
 8 }S[N];
 9 bool ins[N];
10 int n,m,sn,dn,head[N],dfn[N],low[N];
11 int cn,tn,col[N],sta[N],size[N],in[N],out[N];
12 void init(){
13     sn=dn=cn=tn=0;
14     for(int i=0;i<=n;i++){
15         head[i]=-1;
16         dfn[i]=0;
17         ins[i]=false;
18     }
19 }
20 void add(int u,int v){
21     S[sn].v=v;
22     S[sn].ne=head[u];
23     head[u]=sn++;
24 }
25 void tarjan(int u){
26     dfn[u]=low[u]=++dn;
27     ins[u]=true;
28     sta[++tn]=u;
29     for(int i=head[u],v;~i;i=S[i].ne){
30         v=S[i].v;
31         if(!dfn[v]){
32             tarjan(v);
33             low[u]=min(low[u],low[v]);
34         }else if(ins[v]) low[u]=min(low[u],dfn[v]);
35     }
36     if(dfn[u]==low[u]){
37         col[u]=++cn;
38         size[cn]=1;
39         ins[u]=false;
40         while(sta[tn]!=u){
41             col[sta[tn]]=cn;
42             size[cn]++;
43             ins[sta[tn--]]=false;
44         }
45         tn--;
46     }
47 }
48 ll solve(){
49     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
50     if(cn==1) return -1;
51     ll ans=1ll*n*(n-1)-m,mins=1e18+9;
52     for(int i=1;i<=cn;i++) in[i]=out[i]=0;
53     for(int i=1,ci,cj;i<=n;i++){
54         ci=col[i];
55         for(int j=head[i];~j;j=S[j].ne){
56             cj=col[S[j].v];
57             if(ci!=cj){
58                 in[cj]++;
59                 out[ci]++;
60             }
61         }
62     }
63     for(int i=1;i<=cn;i++)
64         if(!in[i]||!out[i]) mins=min(mins,1ll*size[i]*(n-size[i]));
65     return ans-mins;
66 }
67 int main() {
68     int t=1,T,u,v;
69     scanf("%d",&T);
70     while(t<=T){
71         scanf("%d%d",&n,&m);
72         init();
73         for(int i=0;i<m;i++){
74             scanf("%d%d",&u,&v);
75             add(u,v);
76         }
77         printf("Case %d: %lld\n",t++,solve());
78     }
79     return 0;
80 }
连边边

 

posted @ 2019-10-10 17:37  新之守护者  阅读(119)  评论(0编辑  收藏  举报