Strongly connected

题意:给出一个n个点,m条边的图,让我们求出最多加几条边,能让其是一个不强连通的图

思路:逆向思维,一个n个点的有向图,有n*(n-1)条边, 

  1.我们先n*(n-1)-m   得到的答案便是在原有图的基础上将其填成完全图的总边数  

  2.然后通过缩点求出缩点后的图

  3.找出入度或出度为1的最少点的一个缩点,然后将n*(n-1)-m这个数再减去minnum*(n-minnum);

    什么意思呢?

      就是我们现在是在一个完全图的基础上,找到删除最少的边,让其成为一个不连通的图;

        所以,我们要找节点数入度或出度为0的缩点,然后在这个点删除与他相接的边

          假如现在是入度为0,就删其他缩点的所有节点连向这一缩点所有点的边,

          假如出度为0,就删这一缩点所有点连向其他缩点的所有节点的边;

    即为答案

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define ll __int64
 6 const int N = 100005;
 7 struct EDG{
 8     int to,next;
 9 }edg[N];
10 int eid,head[N];
11 int low[N],dfn[N],vist[N],num[N],id[N],deep,stack1[N],tn,top;
12 int in[N],out[N];
13 
14 void init(){
15     eid=tn=top=deep=0;
16     memset(head,-1,sizeof(head));
17     memset(vist,0,sizeof(vist));
18     memset(in,0,sizeof(in));
19     memset(out,0,sizeof(out));
20     memset(num,0,sizeof(num));
21 }
22 void addEdg(int u,int v){
23     edg[eid].to=v; edg[eid].next=head[u]; head[u]=eid++;
24 }
25 void tarjer(int u){
26     stack1[++top]=u;
27     vist[u]=1;
28     deep++;
29     low[u]=dfn[u]=deep;
30     for(int i=head[u]; i!=-1; i=edg[i].next){
31         int v=edg[i].to;
32         if(vist[v]==0){
33             vist[v]=1;
34             tarjer(v);
35             low[u]=min(low[u],low[v]);
36         }
37         else if(vist[v]==1)
38             low[u]=min(low[u],dfn[v]);
39     }
40     if(low[u]==dfn[u]){
41         tn++;
42         do{
43             vist[stack1[top]]=2;
44             num[tn]++;
45             id[stack1[top]]=tn;
46         }while(stack1[top--]!=u);
47 
48     }
49 }
50 ll solve(int n,int m){
51     ll ans=n*(n-1)-m;
52     int minnum=N;
53     for(int i=1; i<=n; i++)
54         if(vist[i]==0)
55          tarjer(i);
56     if(tn==1) return -1;
57     for(int u=1;u<=n;u++)
58     for(int i=head[u];i!=-1;i=edg[i].next){
59         int v=edg[i].to;
60         if(id[u]!=id[v])
61             in[id[v]]++,out[id[u]]++;
62     }
63     for(int i=1; i<=tn; i++)
64     if(in[i]==0||out[i]==0)
65         minnum=min(minnum,num[i]);
66     ans-=minnum*(n-minnum);
67     return ans;
68 }
69 int main()
70 {
71     int T,n,m,c=0,a,b;
72     scanf("%d",&T);
73     while(T--){
74         scanf("%d%d",&n,&m);
75         init();
76         for(int i=1; i<=m; i++){
77             scanf("%d%d",&a,&b);
78             addEdg(a,b);
79         }
80         printf("Case %d: %I64d\n",++c,solve(n,m));
81     }
82     return 0;
83 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/12530846.html