• HDU 2767 Proving Equivalences(强连通分量)


     

    题目大意

     

    一个有向图 n(1<=n<=20000) 个点 m(0<=m<=50000) 条边

    问至少添加几条边,使得整个图是一个强连通图

     

    做法分析

     

    先缩点,然后找出 DAG 中入度为 0 的点的个数和出度为 0 的点的个数,输出较大者(PS:这是一个结论)

     

    参考代码

     

    HDU 2767
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <stack>
     5 
     6 using namespace std;
     7 
     8 struct Edge
     9 {
    10     int en, next;
    11     Edge() {}
    12     Edge(int a, int b)
    13     {
    14         en=a, next=b;
    15     }
    16 } edge[50006];
    17 int head[20006], tot;
    18 int dfn[20006], low[20006], T, in[20006];
    19 int id[20006], ind;
    20 stack<int> S;
    21 int t, n, m;
    22 
    23 void add_edge(int st, int en)
    24 {
    25     edge[tot]=Edge(en, head[st]);
    26     head[st]=tot++;
    27 }
    28 
    29 void tarjan(int u)
    30 {
    31     dfn[u]=low[u]=T++;
    32     S.push(u), in[u]=1;
    33     for(int e=head[u]; e!=-1; e=edge[e].next)
    34     {
    35         int v=edge[e].en;
    36         if(dfn[v]==-1)
    37         {
    38             tarjan(v);
    39             low[u]=min(low[u], low[v]);
    40         }
    41         else if(in[v] && dfn[v]<low[u]) low[u]=dfn[v];
    42     }
    43     if(dfn[u]==low[u])
    44     {
    45         ind++;
    46         for(int v; v=S.top(); )
    47         {
    48             id[v]=ind;
    49             in[v]=0, S.pop();
    50             if(v==u) break;
    51         }
    52     }
    53 }
    54 
    55 int main()
    56 {
    57     scanf("%d", &t);
    58     for(int ca=1; ca<=t; ca++)
    59     {
    60         scanf("%d%d", &n, &m);
    61         memset(head, -1, sizeof head);
    62         tot=0;
    63         for(int i=0, st, en; i<m; i++)
    64         {
    65             scanf("%d%d", &st, &en);
    66             add_edge(st, en);
    67         }
    68         memset(in, 0, sizeof in);
    69         memset(dfn, -1, sizeof dfn);
    70         ind=-1;
    71         while(!S.empty()) S.pop();
    72         for(int i=1; i<=n; i++)
    73             if(dfn[i]==-1) tarjan(i);
    74         if(ind==0)
    75         {
    76             printf("0\n");
    77             continue;
    78         }
    79         memset(dfn, 0, sizeof dfn);
    80         memset(low, 0, sizeof low);
    81         for(int i=1; i<=n; i++)
    82         {
    83             for(int e=head[i]; e!=-1; e=edge[e].next)
    84             {
    85                 if(id[i]!=id[edge[e].en]) dfn[id[i]]++, low[id[edge[e].en]]++;
    86             }
    87         }
    88         int ans1=0, ans2=0;
    89         for(int i=0; i<=ind; i++)
    90         {
    91             if(dfn[i]==0) ans1++;
    92             if(low[i]==0) ans2++;
    93         }
    94         printf("%d\n", max(ans1, ans2));
    95     }
    96     return 0;
    97 }

    AC通道

    HDU 2767 Proving Equivalences

  • 相关阅读:
    Compact Framework访问内嵌资源文件
    RBAC权限设计图 [转]
    c# 中判断用户是否按下CTRL键
    分享开发soket经验 我的基于socket的持久层 [转]
    没事教宝宝画画
    界面开发(一)[转]
    Winform中多国语言窗体的设计以及.NET中资源文件的使用[转]
    我眼中的理想系统
    C# WinForm开发系列 Socket/WCF/Rometing/Web Services[转]
    基于RBAC的权限设计模型[转]
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/2964065.html
Copyright © 2020-2023  润新知