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\n", 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 }

代码君

时间: 2024-10-22 03:52:56

HDU 3639 SCC Hawk-and-Chicken的相关文章

(tarjan/+DFS+反向建图) hdu 3639

G - Hawk-and-Chicken Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3639 Description Kids in kindergarten enjoy playing a game called Hawk-and-Chicken. But there always exists a big problem: ev

hdu 3639 有向图缩点+建反向图+搜索

题意:给个有向图,每个人可以投票(可以投很多人,一次一票),但是一个人只能支持一人一次,支持可以传递,自己支持自己不算,被投支持最多的人. 开始想到缩点,然后搜索,问题是有一点想错了!以为支持按票数计算,而不是按人数!还各种树形dp/搜索求可以到达边数..提交WA了... 又反复读了题目之后才发现..错误..只要人数就行...问题简单了许多... 缩点成有向无环图后:每个SCC中支持的人数就是scc里面的人,要求可到达的点最多的点,当然要放过来求方便:反向图那个点可以到达的点最多!于是建反向图直

HDU 3639 Hawk-and-Chicken(强连通)

HDU 3639 Hawk-and-Chicken 题目链接 题意:就是在一个有向图上,满足传递关系,比如a->b, b->c,那么c可以得到2的支持,问得到支持最大的是谁,并且输出这些人 思路:先强连通的缩点,然后逆向建图,对于每个出度为0的点,进行dfs求哪些点可达这个点 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #inclu

HDU 3639 Hawk-and-Chicken (强连通分量+树形DP)

题目地址:HDU 3639 先用强连通分量缩点,缩点之后,再重新按缩点之后的块逆序构图,每个块的值是里边缩的点的个数,那么得到选票的最大的一定是重新构图后入度为0的块,然后求出来找最大值即可. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h>

[tarjan] hdu 3639 Hawk-and-Chicken

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3639 Hawk-and-Chicken Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1986    Accepted Submission(s): 575 Problem Description Kids in kindergarte

HDU 3639 Hawk-and-Chicken

Hawk-and-Chicken Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1979    Accepted Submission(s): 570 Problem Description Kids in kindergarten enjoy playing a game called Hawk-and-Chicken. But t

HDU 3639 Hawk-and-Chicken(强连通缩点+反向建图)

http://acm.hdu.edu.cn/showproblem.php?pid=3639 题意: 有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两票),输出最多能获得的票数是多少张和获得最多票数的人是谁? 思路: 先强连通缩点反向建图,在计算强连通的时候,需要保存每个连通分支的结点个数. 为什么要反向建图呢?因为要寻找票数最多的,那么肯定是入度为0的点,然后dfs计算它的子节点的

hdu 3639 Hawk-and-Chicken 【强连通分量+反向建图dfs】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3639 题意:有n个人,m条边,每条边代表u给v投一票,票可以传递,比如A->B,B->C,这时C可以得到2票,求出得到最大票数的人有哪些. 分析:从一个强连通到另一个强连通分量的贡献为这两个强连通分量大小和减一.显然票数最大的人在图的端点. 将缩点后的图方向,可以得到一些入度为0的点,用DFS可以求出这些点的票数,最后去求出最大票数. 代码: <pre name="code"

HDU 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)

Problem Description Kids in kindergarten enjoy playing a game called Hawk-and-Chicken. But there always exists a big problem: every kid in this game want to play the role of Hawk. So the teacher came up with an idea: Vote. Every child have some nice