• hDU2767Equivalences【强连通缩点+添加多少条边可以使有向图强连通】


    大意:

    告诉你有n个点  m条单向边  问最少添加多少条边能将该图变成强连通

    分析:

    先用强连通进行缩点  缩成一个有向无环图 

    然后我们考虑如何才能使 这个有向无环图变成一个强连通

    我的第一反应是求最小路径覆盖  然后再首尾相连  结果时间复杂度承受不住

    其实想到这里可以大胆猜想一下了   

    刚刚提到了  首尾连接这个思想

    我们只要统计有多少个头多少个尾  然后用尾去连接头就好了  答案就是首尾最大值
    统计首尾也就是统计入度出度为0的点的个数

    需要注意的是  若强连通缩点之后点缩成了一个  那么这个点本身就是一个强连通

    代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <map>
      5 #define clr(x) memset(x, 0, sizeof(x))
      6 using namespace std;
      7 int min(int a, int b) {
      8     return a > b ? b : a;
      9 }
     10 
     11 const int maxn = 500005;
     12 const int maxm = 500005;
     13 
     14 struct Edge {
     15     int to, next;
     16 }e[maxm];
     17 int tot;
     18 int head[maxn];
     19 int id[maxn];
     20 
     21 void add(int u, int v) {
     22     e[tot].to = v;
     23     e[tot].next = head[u];
     24     head[u] = tot++;
     25 }
     26 int n, m;
     27 
     28 int s[maxn];
     29 int ins[maxn];
     30 int s_cnt;
     31 int id_cnt;
     32 int cnt;
     33 int dfn[maxn], low[maxn];
     34 void dfs(int u) {
     35     s[s_cnt++] = u;
     36     ins[u] = 1;
     37     dfn[u] = low[u] = cnt++;
     38     for(int i = head[u]; i; i = e[i].next) {
     39         int v = e[i].to;
     40         if(!dfn[v]) {
     41             dfs(v);
     42             low[u] = min(low[u], low[v]);
     43         } else if(ins[v]) {
     44             low[u] = min(low[u], dfn[v]);
     45         }
     46     }
     47     if(dfn[u] == low[u]) {
     48         int x;
     49         id_cnt++;
     50         do {
     51             x = s[--s_cnt];
     52             ins[x] = 0;
     53             id[x] = id_cnt;
     54         } while(x != u);
     55     }
     56 }
     57 
     58 void init() {
     59     clr(head);
     60     clr(dfn);
     61     clr(low);
     62     clr(id);
     63     clr(ins);
     64     cnt = 1;
     65     s_cnt = 1;
     66     id_cnt = 0;
     67     tot = 1;
     68 }
     69 int ind[maxn], outd[maxn];
     70 
     71 int main() {
     72     int t;
     73     scanf("%d",&t);
     74     int u, v;
     75     while(t--) {
     76         scanf("%d %d",&n, &m);
     77         init();
     78         for(int i = 1; i <= m; i++) {
     79             scanf("%d %d",&u, &v);
     80             add(u, v);
     81         }
     82         for(int i = 1; i <= n; i++) {
     83             if(!dfn[i]) {
     84                 dfs(i);
     85             }
     86         }
     87         if(id_cnt == 1) {
     88             printf("%d
    ", 0);
     89             continue;
     90         }
     91         int ans1 = 0; int ans2 = 0;
     92         clr(ind); clr(outd);
     93         for(int i = 1; i <= n; i++) {
     94             for(int j = head[i]; j; j = e[j].next) {
     95                 int x = e[j].to;
     96                 if(id[i] != id[x]) {
     97                     ind[id[x]]++;
     98                     outd[id[i]]++;
     99                 }
    100             }
    101         }
    102         for(int i = 1; i <= id_cnt; i++) {
    103             if(ind[i] == 0) ans1++;
    104             if(outd[i] == 0) ans2++;
    105         } 
    106         if(ans1 < ans2) ans1 = ans2;
    107         printf("%d
    ", ans1);
    108     }
    109     return 0;
    110 }
    111 
    112     
    View Code
  • 相关阅读:
    转 [Lucene.Net] 基本用法
    万商网与Alibaba等的比较
    B2B闯入者 新势力正在崛起
    项目管理随想一
    【转载】/proc目录中的重要信息
    文件名乱码转换器
    C函数调用中对入参取地址引发的问题
    编译通过的代码不算什么,一眼能看懂的代码才算好代码
    Handler使用
    删除system/app下的apk
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/4333091.html
Copyright © 2020-2023  润新知