Hawk-and-Chicken

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2409    Accepted Submission(s): 712

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 handkerchiefs, and if he/she think someone is suitable for the role of Hawk, he/she gives a handkerchief to this kid, which means this kid who is given the handkerchief win the support. Note
the support can be transmitted. Kids who get the most supports win in the vote and able to play the role of Hawk.(A note:if A can win

support from B(A != B) A can win only one support from B in any case the number of the supports transmitted from B to A are many. And A can't win the support from himself in any case.

If two or more kids own the same number of support from others, we treat all of them as winner.

Here's a sample: 3 kids A, B and C, A gives a handkerchief to B, B gives a handkerchief to C, so C wins 2 supports and he is choosen to be the Hawk.
 
Input
There are several test cases. First is a integer T(T <= 50), means the number of test cases.

Each test case start with two integer n, m in a line (2 <= n <= 5000, 0 <m <= 30000). n means there are n children(numbered from 0 to n - 1). Each of the following m lines contains two integers A and B(A != B) denoting that the child numbered A give a handkerchief
to B.
 
Output
For each test case, the output should first contain one line with "Case x:", here x means the case number start from 1. Followed by one number which is the totalsupports the winner(s) get.

Then follow a line contain all the Hawks' number. The numbers must be listed in increasing order and separated by single spaces.
 
Sample Input
2
4 3
3 2
2 0
2 1 3 3
1 0
2 1
0 2
 
Sample Output
Case 1: 2
0 1
Case 2: 2
0 1 2
 

题意:如今有n个孩子正在玩游戏,完毕一个传递的游戏,举个样例,A传递到B小朋友,然后B小朋友传递给C小朋友。那么此时,C小朋友将拥有2的传递值,C是胜利者,若C又传递回A。那么A,B,C三者都拥有传递值为2的胜利者。问胜利着获得的最大传递值,以及胜利者的编号(可能有多个)。

解析:这题的 n的数据量为5000, 暴力肯定是不行的,有题意可知:如有 A - > B,  B - > C, C - >A。那么A。B,C都是拥有传递值为2的胜利者。

所以我们能够先缩点求出SCC。对每一个SCC内的点来说。 它们的传递值是一样的,但要明确:假设从一个SCC:a, 传到还有一个SCC:b, 即 a
- > b。传递的值为SCC a 内部点的个数。这点要清楚

并且我们知道,胜利者肯定在那些出度为0的SCC中,所以我们能够从每一个入度为0的SCC開始搜索,DFS遍历一遍,得到每一个出度为0的SCC的传递值,找出最大的就可以,

但这样的思路是不正确的,由于入度为0的SCC的个数肯定远远的大于出度为0的SCC个数,并且这题的n是很大的。枚举每一个入度为0的SCC然后DFS遍历一遍肯定会超时。

所以我们要反向建图, 这样每次从入度为0的SCC【即正向建边出度为0 的SCC】開始DFS,就能够得到每一个入度为0的SCC的传递值。

找出当中传递值最大的。这里还有注意

当我们找这个传递值最大的SCC :A 时,我们把这SCC的传递值多算了1,由于我们算的时候是累加的每一个SCC中点的个数。

当找到传递值最大的SCC A时,它内部的传递值为  内部点的个数 - 1。(如A - > B,  B - > C, C - >A,传递值为2),但我们加的时候没有 - 1,所以最后的结果 - 1才是正确答案,这点比較绕,我解释的也不是太清楚。读者自己多想想。不是太难明确。

明天開始刷独立集,2-SAT。 强连通就先做到这。。

这应该是有史以来自己写的最长的解析了,曾经直接总是懒得写题解。认为能写出AC代码即可了,有时懒省事就粘一下别人的。但如今才发现自己写解析的时候收获才最大的,曾经真真真真真蠢。能把自己的思路完整的用文字呈现出来。肯定是比較理解解题的思路了。以后解析都要自己写。还要好好写。加油阿欢。

<pre name="code" class="cpp">#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define maxn 5000 + 500
#define maxm 30000 + 3000
using namespace std; struct node{
int u, v, next;
}; node edge[maxm]; int head[maxn], cnt;
int low[maxn], dfn[maxn];
int dfs_clock;
int Belong[maxn];
int scc_clock;
bool Instack[maxn];
int Stack[maxn], top;
bool vis[maxn];//记录缩点后的SCC是否訪问
int in[maxn];//记录SCC的入度
int num[maxn];//记录每一个SCC能得到的最大手帕数
vector<int>scc[maxn];//存储每一个SCC中的节点
vector<int> Map[maxn];//存储缩点后新图
int n, m, k; void init(){
cnt = 0;
memset(head, -1, sizeof(head));
} void add(int u, int v){
edge[cnt] = {u, v, head[u]};
head[u] = cnt++;
} void getmap(){
scanf("%d%d", &n, &m);
int a, b;
while(m--){
scanf("%d%d", &a, &b);
a++, b++;
add(a, b);
}
} void tarjan(int u){
int v;
low[u] = dfn[u] = ++dfs_clock;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next){
v = edge[i].v;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(Instack[v])
low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]){
scc_clock++;
scc[scc_clock].clear();
do{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc_clock;
scc[scc_clock].push_back(v);
}while(u != v);
}
} void find(){
memset(low, 0, sizeof(low));
memset(dfn, 0, sizeof(dfn));
memset(Belong, 0, sizeof(Belong));
memset(Stack, 0, sizeof(Stack));
memset(Instack, false, sizeof(Instack));
dfs_clock = scc_clock = top = 0;
for(int i = 1; i <= n; ++i)
if(!dfn[i]) tarjan(i);
} void suodian(){//缩点新建图
for(int i = 1; i <= scc_clock; ++i){
Map[i].clear();
in[i] = 0;
}
for(int i = 0; i < cnt; ++i){
int u = Belong[edge[i].u];
int v = Belong[edge[i].v];
if(u != v){
Map[v].push_back(u);//反向建边
in[u]++;
}
}
} int ans;
void DFS(int u){
vis[u] = true;
ans += scc[u].size();
for(int i = 0; i < Map[u].size(); ++i){
int v = Map[u][i];
if(!vis[v]){
DFS(v);
}
}
} void solve(){
int sum = -1;
for(int i = 1; i <= scc_clock; ++i){
num[i] = 0;
if(in[i] == 0){
memset(vis, false, sizeof(vis));
ans = 0;
DFS(i);
num[i] = ans;
sum = max(num[i], sum);
}
}
printf("Case %d: %d\n", k++, sum - 1);//多算1,要减去1
int flag = 0;
for(int i = 1; i <= n; ++i){
if(num[Belong[i]] == sum){
if(!flag) printf("%d", i - 1);
else printf(" %d", i - 1);
flag = 1;
}
}
printf("\n");
} int main(){
int T;
scanf("%d", &T);
k = 1;
while(T--){
init();
getmap();
find();
suodian();
solve();
}
return 0;
}

HPU 3639--Hawk-and-Chicken【SCC缩点反向建图 &amp;&amp; 求传递的最大值】的更多相关文章

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

    http://acm.hdu.edu.cn/showproblem.php?pid=3639 题意: 有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则 ...

  2. HDU 3861--The King’s Problem【scc缩点构图 &amp;&amp; 二分匹配求最小路径覆盖】

    The King's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  3. [CERC2017]Intrinsic Interval[scc+线段树优化建图]

    题意 给定一个长度为 \(n\) 的排列,有 \(q\) 次询问,每次询问一个区间 \([l,r]\) ,找到最小的包含 \([l,r]\) 的区间,满足这个区间包含了一段连续的数字. \(n\leq ...

  4. BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]

    2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...

  5. cf949C 建模,SCC缩点

    /* 给定n个数据中心,m份资料,每份资料在其中的两个中心备份,一天可供下载的时间是h小时 中心i在第hi小时需要维护,无法下载 现在要将一些中心的维护时间往后推1小时,使得任意时刻每份资料都可以被下 ...

  6. POJ 3126 --Father Christmas flymouse【scc缩点构图 &amp;&amp; SPFA求最长路】

    Father Christmas flymouse Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 3007   Accep ...

  7. bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp

    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...

  8. poj 3592 Instantaneous Transference 【SCC +缩点 + SPFA】

    Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6204   Accep ...

  9. HDU 3072--Intelligence System【SCC缩点新构图 &amp;&amp; 求连通全部SCC的最小费用】

    Intelligence System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

随机推荐

  1. STL学习笔记3--deque

    看这一节,是为了下一节的使用,在ogre3d里有些操作要使用到deque. C++ Deque(双向队列) 的使用 Deque结合了vector  和list  优缺点,是一种使用简单的容器. deq ...

  2. SpringBoot中Async异步方法和定时任务介绍

    1.功能说明 Spring提供了Async注解来实现方法的异步调用. 即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行 ...

  3. Recommender System

    推荐系统我们都很熟悉,淘宝推荐用户可能感兴趣的产品,搜索引擎帮助用户发现可能感兴趣的东西,这些都是推荐系统的内容.接下来讲述一个电影推荐的项目. Netflix 电影推荐系统 这个项目是使用的Netf ...

  4. webpack vue-cli 常见问题总结

    1. webpack打包压缩 ES6 js..vue报错: ERROR in js/test.js from UglifyJs Unexpected token punc ?(?, expected ...

  5. nyoj 题目5 Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Given two strings A and B, whose alp ...

  6. Dos中查看mysql数据时 中文乱码

    使用jsp页面查看数据时可以正确显示中文,但是dos窗口查看数据时中文显示乱码. 上网查了一下原因:之所以会显示乱码,就是因为MySQL客户端输出窗口显示中文时使用的字符编码不对造成的,可以使用如下的 ...

  7. Newton 插值法

    定义 $f(x)$ 关于 $x_0, x_1, \dots, x_k$ 的 $k$ 阶均差(差商)记做 $ f [x_0, x_1, \dots, x_k] $,均差是递归定义的,有两种等价定义 \b ...

  8. 个人环境搭建——版本控制SVN

    版本控制SVN SVN服务器配置: 第一部分:svn服务器搭建(主要是四步走) 参考:http://www.son1c.cn/show/920.html 一,安装Subversion sudo apt ...

  9. 密码 (pasuwado)

    密码 (pasuwado) 题目描述 哪里有压迫,哪里就有反抗. moreD的宠物在法庭的帮助下终于反抗了.作为一只聪明的宠物,他打算把魔法使moreD的魔法书盗去,夺取moreD的魔法能力.但mor ...

  10. 【bzoj3585】mex 线段树 mex,sg

    Description 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l, ...