• HDU 1827 强连通 缩点 Summer Holiday


    求出强连通分量,因为强连通中只要有一个人被通知到了,所有人都能被通知到。

    缩点以后形成一个DAG,找出那些入度为0的点,累加上它们的权值就是答案。一个点的权值等于SCC中权值最小的那个点。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 #include <stack>
     7 using namespace std;
     8 
     9 const int maxn = 1000 + 10;
    10 
    11 int n, m;
    12 int w[maxn], cost[maxn];
    13 vector<int> G[maxn];
    14 
    15 stack<int> S;
    16 int pre[maxn], lowlink[maxn], sccno[maxn];
    17 int dfs_clock, scc_cnt;
    18 
    19 void dfs(int u)
    20 {
    21     pre[u] = lowlink[u] = ++dfs_clock;
    22     S.push(u);
    23     for(int i = 0; i < G[u].size(); i++)
    24     {
    25         int v = G[u][i];
    26         if(!pre[v])
    27         {
    28             dfs(v);
    29             lowlink[u] = min(lowlink[u], lowlink[v]);
    30         }
    31         else if(!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]);
    32     }
    33     if(lowlink[u] == pre[u])
    34     {
    35         scc_cnt++;
    36         for(;;)
    37         {
    38             int x = S.top(); S.pop();
    39             sccno[x] = scc_cnt;
    40             if(x == u) break;
    41         }
    42     }
    43 }
    44 
    45 void find_scc()
    46 {
    47     dfs_clock = scc_cnt = 0;
    48     memset(sccno, 0, sizeof(sccno));
    49     memset(pre, 0, sizeof(pre));
    50     for(int i = 1; i <= n; i++) if(!pre[i]) dfs(i);
    51 }
    52 
    53 int indeg[maxn];
    54 
    55 int main()
    56 {
    57     while(scanf("%d%d", &n, &m) == 2)
    58     {
    59         for(int i = 1; i <= n; i++) G[i].clear();
    60         for(int i = 1; i <= n; i++) scanf("%d", w + i);
    61         while(m--)
    62         {
    63             int u, v; scanf("%d%d", &u, &v);
    64             G[u].push_back(v);
    65         }
    66 
    67         find_scc();
    68 
    69         memset(cost, 0x3f, sizeof(cost));
    70         for(int i = 1; i <= n; i++) cost[sccno[i]] = min(cost[sccno[i]], w[i]);
    71 
    72         memset(indeg, 0, sizeof(indeg));
    73         for(int i = 1; i <= n; i++)
    74         {
    75             for(int j = 0; j < G[i].size(); j++)
    76             {
    77                 int u = sccno[i], v = sccno[G[i][j]];
    78                 if(u == v) continue;
    79                 indeg[v]++;
    80             }
    81         }
    82 
    83         int ans1 = 0, ans2 = 0;
    84         for(int i = 1; i <= scc_cnt; i++) if(!indeg[i]) { ans1++; ans2 += cost[i]; }
    85         printf("%d %d
    ", ans1, ans2);
    86     }
    87 
    88     return 0;
    89 }
    代码君
  • 相关阅读:
    x64共享库中的位置无关代码(PIC)
    windows库的创建和使用:静态库+动态库
    溃烂中的代码
    微信考勤玩法曝光!
    Android自己定义ViewGroup(二)——带悬停标题的ExpandableListView
    WPF对象级资源的定义与查找
    java List转换和数组互转
    maven 打包构建相关命令
    java8 lambda表达式
    Mysql INSTR函数
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4717522.html
Copyright © 2020-2023  润新知