• kuangbin专题 专题九 连通图 Strongly connected HDU


    题目链接:https://vjudge.net/problem/HDU-4635

    题目:有向图,给定若干个连通图,求最多还能添加几条边,添完边后,图仍然要满足

    (1)是简单图,即没有重边或者自环

    (2)不是有向强连通图

    思路:我们可以这么想,n个顶点,一个有向图边数最多,就是有向完全图,则边数为n*(n-1)。

    要满足不是强连通图,我们可以假设有一个tarjan缩成的点(scc),它不能到达其他所有点,或者其他所有点

    不能到达它,假设这个scc有k个顶点,也就是说,k*(n-k)条边是不存在的,那么最大添加边数应该是  n*(n-1) - k*(n-k) - m(本来有的边) ----  ①

    给定的图情况不确定,我们先进行tarjan缩点,分成若干个scc,每个scc中也记录各自scc中的顶点数,然后进行scc的入度出度统计。

    为使添加的边能最多,我们选所有的入度为0或者出度为0的scc 套入 公式①,选最大即可。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 typedef long long ll;
      7 const int N = (int)1e5+10;
      8 int n,m,tot,tim,scc,top;
      9 int head[N],dfn[N],low[N],scc_no[N],s[N],ins[N];
     10 struct node{
     11     int to;
     12     int nxt;
     13 }e[N];
     14 struct col{
     15     int ru;
     16     int chu;
     17     int cnt;
     18 }col[N];//强连通分量
     19 
     20 void init(){
     21     for(int i = 0; i <= n; ++i){
     22         head[i] = -1;
     23         col[i].ru = col[i].chu = dfn[i] = 0;
     24     }
     25     tot = tim = scc = 0;
     26 }
     27 
     28 inline void add(int u,int v){
     29     e[tot].to = v;
     30     e[tot].nxt = head[u];
     31     head[u] = tot++;
     32 }
     33 
     34 void tarjan(int now,int pre){
     35     dfn[now] = low[now] = ++tim;
     36     ins[now] = 1; s[top++] = now;
     37     int to;
     38     for(int o = head[now]; ~o; o = e[o].nxt){
     39         to = e[o].to;
     40      //   if(to == pre) continue;
     41         if(!dfn[to]){
     42             tarjan(to,now);
     43             low[now] = min(low[now],low[to]);
     44         }
     45         else if(ins[to]) low[now] = min(low[now],dfn[to]);
     46     }
     47 
     48     if(dfn[now] == low[now]){
     49         int x,cnt = 0;
     50         ++scc;
     51         do{
     52             x = s[--top];
     53             ins[x] = 0;
     54             scc_no[x] = scc;
     55             ++cnt;
     56         }while(now != x);
     57         col[scc].cnt = cnt;//每个强连通分量包含几个点
     58     }
     59 }
     60 
     61 //入度出度统计
     62 void du_cnt(){
     63     int to;
     64     for(int now = 1; now <= n; ++now){
     65         for(int o = head[now]; ~o; o = e[o].nxt){
     66             to = e[o].to;
     67             if(scc_no[to] == scc_no[now]) continue;
     68                 ++col[scc_no[to]].ru;
     69                 ++col[scc_no[now]].chu;
     70         }
     71     }
     72 }
     73 
     74 void solve(int _case){
     75     for(int i = 1; i <= n; ++i)
     76         if(!dfn[i]) tarjan(i,i);
     77         
     78     ll ans = (ll)n*(n-1) - m;
     79     ll useless = (1LL) << 60;
     80     du_cnt();
     81     for(int i = 1; i <= scc; ++i){
     82         if(!col[i].ru || !col[i].chu){
     83             useless = min(useless,(ll)col[i].cnt*(n-col[i].cnt));
     84         }
     85     }
     86     if(scc == 1) printf("Case %d: -1
    ",_case);
     87     else printf("Case %d: %lld
    ",_case,ans-useless);
     88 }
     89 
     90 int main(){
     91 
     92     int T,u,v;
     93     scanf("%d",&T);
     94     for(int i = 1; i <= T; ++i){
     95         scanf("%d%d",&n,&m);
     96         init();
     97         for(int x = 1; x <= m; ++x){
     98             scanf("%d%d",&u,&v);
     99             add(u,v);
    100         }
    101         solve(i);
    102     }
    103 
    104     return 0;
    105 }
  • 相关阅读:
    边缘引导插值/方向卷积插值
    cout显示Mat类对象报错Access Violation
    图像特征点匹配C代码
    TF-IDF(词频-逆向文件频率)用于文字分类
    Jsp中如何通过Jsp调用Java类中的方法
    根据wsdl文件,soupUI生成webservice客户端代码
    根据wsdl,axis2工具生成客户端代码
    根据wsdl,apache cxf的wsdl2java工具生成客户端、服务端代码
    根据wsdl,基于wsimport生成代码的客户端
    Mysql截取和拆分字符串函数用法
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/12205601.html
Copyright © 2020-2023  润新知