zoukankan      html  css  js  c++  java
  • HDU 3639 SCC Hawk-and-Chicken

    求SCC缩点,统计出每个SCC中的点的个数。

    然后统计能到达u的最多的点的个数,可以反向建图,再dfs一遍统计出来。

    最后说一下,有必要开一个标记数组,因为测试数据中有重边,结果无限WA。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <stack>
      7 using namespace std;
      8 
      9 const int maxn = 5000 + 10;
     10 int n, m;
     11 vector<int> G[maxn];
     12 
     13 stack<int> S;
     14 int pre[maxn], lowlink[maxn], sccno[maxn], sz[maxn], dfs_clock, scc_cnt;
     15 
     16 void dfs(int u)
     17 {
     18     pre[u] = lowlink[u] = ++dfs_clock;
     19     S.push(u);
     20 
     21     for(int i = 0; i < G[u].size(); i++)
     22     {
     23         int v = G[u][i];
     24         if(!pre[v])
     25         {
     26             dfs(v);
     27             lowlink[u] = min(lowlink[u], lowlink[v]);
     28         }
     29         else if(!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]);
     30     }
     31 
     32     if(pre[u] == lowlink[u])
     33     {
     34         scc_cnt++;
     35         for(;;)
     36         {
     37             int x = S.top(); S.pop();
     38             sccno[x] = scc_cnt;
     39             sz[scc_cnt]++;
     40             if(x == u) break;
     41         }
     42     }
     43 }
     44 
     45 void find_scc()
     46 {
     47     dfs_clock = scc_cnt = 0;
     48     memset(pre, 0, sizeof(pre));
     49     memset(sccno, 0, sizeof(sccno));
     50     memset(sz, 0, sizeof(sz));
     51     for(int i = 0; i < n; i++) if(!pre[i]) dfs(i);
     52 }
     53 
     54 int support[maxn];
     55 int indeg[maxn];
     56 bool vis[maxn];
     57 vector<int> G2[maxn];
     58 
     59 int dfs2(int u)
     60 {
     61     int ans = sz[u];
     62     vis[u] = true;
     63     for(int i = 0; i < G2[u].size(); i++)
     64     {
     65         int v = G2[u][i];
     66         if(vis[v]) continue;
     67         ans += dfs2(v);
     68     }
     69     return ans;
     70 }
     71 
     72 int main()
     73 {
     74     int T; scanf("%d", &T);
     75     for(int kase = 1; kase <= T; kase++)
     76     {
     77         scanf("%d%d", &n, &m);
     78         for(int i = 0; i < n; i++) G[i].clear();
     79         while(m--)
     80         {
     81             int u, v; scanf("%d%d", &u, &v);
     82             G[u].push_back(v);
     83         }
     84 
     85         find_scc();
     86 
     87         memset(indeg, 0, sizeof(indeg));
     88         for(int i = 1; i <= scc_cnt; i++) G2[i].clear();
     89         for(int i = 0; i < n; i++)
     90             for(int j = 0; j < G[i].size(); j++)
     91             {
     92                 int u = sccno[i], v = sccno[G[i][j]];
     93                 if(u == v) continue;
     94                 indeg[u]++;
     95                 G2[v].push_back(u);
     96             }
     97 
     98         int ans = 0;
     99         for(int i = 1; i <= scc_cnt; i++) if(!indeg[i])
    100         {
    101             memset(vis, false, sizeof(vis));
    102             support[i] = dfs2(i);
    103             ans = max(ans, support[i]);
    104         }
    105 
    106         printf("Case %d: %d
    ", kase, ans - 1);
    107         bool flag = false;
    108         for(int i = 0; i < n; i++)
    109         {
    110             int u = sccno[i];
    111             if(!indeg[u] && support[u] == ans)
    112             {
    113                 if(flag) printf(" ");
    114                 printf("%d", i);
    115                 flag = true;
    116             }
    117         }
    118         puts("");
    119     }
    120 
    121     return 0;
    122 }
    代码君
  • 相关阅读:
    np背包问题【算法:折半枚举】
    数字游戏【后缀积问题,一个数学分析问题】
    bfs求最短路径
    利用费马小定理求逆元
    [蓝桥杯2016初赛]剪邮票【全排列,连通块】
    np背包问题【算法:折半枚举】
    火星救[数学,一点前缀和]
    bfs求最短路径
    检测一个正整数是否是2的N次方
    IIS与asp.net身份认证
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4719617.html
Copyright © 2011-2022 走看看