zoukankan      html  css  js  c++  java
  • HDU 4635 Strongly connected ——(强连通分量)

      好久没写tarjan了,写起来有点手生,还好1A了- -。

      题意:给定一个有向图,问最多添加多少条边,让它依然不是强连通图。

      分析:不妨考虑最大时候的临界状态(即再添加一条边就是强连通图的状态),假设这时候的边的数量是F,那么答案就是F-m(m是一开始边的数量)。因此,F越大,答案越大。那么,怎么考虑F的值呢?最后的状态一定是这样的:整个图不是强连通的,但是他的两个分部x和y都是强连通的,并且其中任意一个分量(不妨设其为x),到另外一个分量(y),x中的每一个点到y中的每一个点都有边,而且,y中的每一个点到x中的每一个点都没有边;另外,x和y内部任意两点间都是有边的。这样的话任意添加一条边都会使得原图变成一个强连通图(因为再添加边只能是y中一点到x一点,这样整个图中任意两点间都可达了)。那么我们不妨设x中点的个数为a,y中点的个数为b=n-a(共有n个点),因此F=a*(a-1)+b*(b-1)+a*b(x到y的边)。这样,ans=F-m,化简得到ans=n*n-a*b-n-m。对a和b进行基本不等式可知,他们相等时乘积最大,因此他们相差最大时ans最大(也可以直接枚举任意两个强连通分量来得到答案)。另外要注意的一点是,x和y必须一个有任意一个是入度或者出度为0的,这样的话,才能使得他们构造成为F的状态。还想提的一点是,一个点也能成为强连通分量。

      具体见代码:

      1 #include <stdio.h>
      2 #include <algorithm>
      3 #include <string.h>
      4 #include <vector>
      5 #include <map>
      6 #include <set>
      7 #include <queue>
      8 #include <iostream>
      9 #include <stdlib.h>
     10 #include <string>
     11 #include <stack>
     12 using namespace std;
     13 const int inf = 0x3f3f3f3f;
     14 typedef long long ll;
     15 typedef pair<int,int> pii;
     16 const int N = 100000 + 5;
     17 
     18 int n,m,dfs_clock,dfn[N],low[N];
     19 int belong[N],scc_cnt,cnt[N],in[N],out[N];
     20 stack<int> S;
     21 vector<int> G[N];
     22 
     23 void init()
     24 {
     25     for(int i=1;i<=n;i++) G[i].clear();
     26     dfs_clock = 0;
     27     memset(dfn,0,sizeof(dfn));
     28     memset(belong,0,sizeof(belong));
     29     scc_cnt = 0;
     30     memset(cnt,0,sizeof(cnt));
     31     memset(in,0,sizeof(in));
     32     memset(out,0,sizeof(out));
     33 }
     34 
     35 void tarjan(int u)
     36 {
     37     dfn[u]=low[u]=++dfs_clock;
     38     S.push(u);
     39     for(int i=0;i<G[u].size();i++)
     40     {
     41         int v = G[u][i];
     42         if(!dfn[v])
     43         {
     44             tarjan(v);
     45             low[u]=min(low[u],low[v]);
     46         }
     47         else if(!belong[v])
     48         {
     49             low[u]=min(low[u],dfn[v]);
     50         }
     51     }
     52     if(low[u]==dfn[u])
     53     {
     54         scc_cnt++;
     55         int num = 0;
     56         for(;;)
     57         {
     58             num ++;
     59             int x = S.top();S.pop();
     60             belong[x] = scc_cnt;
     61             if(x==u) break;
     62         }
     63         cnt[scc_cnt] = num;
     64     }
     65 }
     66 
     67 void solve()
     68 {
     69     for(int i=1;i<=n;i++)
     70     {
     71         if(!dfn[i]) tarjan(i);
     72     }
     73 
     74     for(int i=1;i<=n;i++)
     75     {
     76         int x = belong[i];
     77         for(int j=0;j<G[i].size();j++)
     78         {
     79             int v = G[i][j];
     80             if(belong[i] == belong[v]) continue;
     81 
     82             int y = belong[v];
     83             out[x]++;
     84             in[y]++;
     85         }
     86     }
     87 
     88     ll ans = 0;
     89     for(int i=1;i<=scc_cnt;i++)
     90     {
     91         if(in[i] && out[i]) continue;
     92 
     93         int a = cnt[i];
     94         int b = n-a;
     95         ans = max(ans,(ll)n*n-(ll)a*b-n-m);
     96     }
     97     if(scc_cnt == 1) ans = -1;
     98     cout << ans << endl;
     99 }
    100 
    101 int main()
    102 {
    103     int T;
    104     scanf("%d",&T);
    105     for(int kase=1;kase<=T;kase++)
    106     {
    107         init();
    108         printf("Case %d: ",kase);
    109         scanf("%d%d",&n,&m);
    110         for(int i=1;i<=m;i++)
    111         {
    112             int u,v;
    113             scanf("%d%d",&u,&v);
    114             G[u].push_back(v);
    115         }
    116         solve();
    117     }
    118 }
  • 相关阅读:
    Android 获取自带浏览器上网记录
    android 中的 ViewPager+ Fragment
    Git分支操作
    图形验证码的识别
    mac平台搭建安卓开发环境
    [报错集合]Uncaught ReferenceError: xxx is not defined
    Centos安装Python3
    VSCode 代码格式化 快捷键
    Mac下用Parallels Desktop安装Ubuntu
    请求头headers
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5681863.html
Copyright © 2011-2022 走看看