[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 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

Author

Dragon

Source

2010 ACM-ICPC Multi-University
Training Contest(19)——Host by HDU

Recommend

lcy   |   We have carefully selected several similar problems for you:  3634 3633 3636 3637 3638

Statistic | Submit | Discuss | Note

题目意思:

给一幅图,求点i,使得能够到达i的点数最多。

解题思路:

tarjan缩点,反向建图,然后dfs统计入度为0的联通分量,求出能够到达的节点数a,比较记录a最大的那些连通分量。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 5500

int low[Maxn],dfn[Maxn],sta[Maxn],sc,bc,n,m,dep;
bool iss[Maxn];
int in[Maxn],nu[Maxn],dei[Maxn],ans,temp;
vector<vector<int> >myv;
vector<vector<int> >tree;
map<int,int>myp[Maxn];
bool vis[Maxn];

void tarjan(int cur)
{
    int ne;

    low[cur]=dfn[cur]=++dep;
    sta[++sc]=cur;
    iss[cur]=true;

    for(int i=0;i<myv[cur].size();i++)
    {
        ne=myv[cur][i];
        if(!dfn[ne])
        {
            tarjan(ne);
            if(low[ne]<low[cur])
                low[cur]=low[ne];
        }
        else if(iss[ne]&&dfn[ne]<low[cur])
            low[cur]=dfn[ne];
    }
    if(low[cur]==dfn[cur])
    {
        bc++;
        do
        {
            ne=sta[sc--];
            iss[ne]=false;
            in[ne]=bc;
            nu[bc]++;
        }while(ne!=cur);
    }
}
void solve()
{
    dep=sc=bc=0;
    memset(iss,false,sizeof(iss));
    memset(dfn,0,sizeof(dfn));
    memset(nu,0,sizeof(nu));

    for(int i=0;i<n;i++)
        if(!dfn[i])
            tarjan(i);
}
void dfs(int cur)
{
    vis[cur]=true;
    temp+=nu[cur];

    for(int j=0;j<tree[cur].size();j++)
    {
        int ne=tree[cur][j];
        if(!vis[ne])
            dfs(ne);
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int t,kcas=0;

   scanf("%d",&t);
   while(t--)
   {
       scanf("%d%d",&n,&m);
       myv.clear();
       myv.resize(n+1);

       for(int i=1;i<=m;i++)
       {
           int a,b;
           scanf("%d%d",&a,&b);
           myv[a].push_back(b);
       }
       solve();

       tree.clear();
       tree.resize(bc+1);
       for(int i=1;i<=bc;i++)
            myp[i].clear();

       memset(dei,0,sizeof(dei));
       for(int i=0;i<n;i++)
       {
           for(int j=0;j<myv[i].size();j++)
           {
               int ne=myv[i][j];
               if(in[ne]!=in[i])
               {
                   if(myp[in[ne]][in[i]]==0)
                   {
                       //system("pause");
                       myp[in[ne]][in[i]]=1;
                       tree[in[ne]].push_back(in[i]);
                       dei[in[i]]++;
                   }
               }
           }
       }
       ans=0;
       /*printf("bc:%d\n",bc);
       for(int i=0;i<n;i++)
            printf("i:%d bei:%d dei:%d\n",i,in[i],dei[in[i]]);*/
       for(int i=1;i<=bc;i++)
       {
           if(!dei[i])
            {
                //printf("i:%d\n",i);
                //system("pause");

                for(int j=1;j<=bc;j++)
                    vis[j]=false;
                temp=0;
                dfs(i);
                nu[i]=temp;
                ans=max(ans,temp);
            }
       }
       printf("Case %d: %d\n",++kcas,ans-1);
       bool fi=true;

       for(int i=0;i<n;i++)
       {
           if(nu[in[i]]==ans)
           {
               if(!fi)
                    putchar(' ');
               else
                    fi=false;
               printf("%d",i);
           }

       }
       putchar('\n');
   }

    return 0;
}
/*
4 4
0 1
0 2
1 3
2 3
*/
时间: 2024-11-08 15:02:01

[tarjan] hdu 3639 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 Hawk-and-Chicken (强连通分量+树形DP)

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

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(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

HDU 3639 Hawk-and-Chicken tarjan缩点+dfs

题意:投票,投票可以传递,当一个人投票时,要把此人的得票数全给被投的那个人,问最后按升序输出得票数最高的人. 想法:显然在一个连通块内的所有点的得票数都是一样的,即:块内点数-1,(1:是他自己本身).所以先要tarjan缩点,然后求出每一个块可以由几个块到达(这里可以反向建边dfs).最后输出最大得票数的人即可. #include<iostream> #include<cstring> #include<cstdio> #include<stack> #i

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 【强连通分量+反向建图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"

[tarjan] hdu 3836 Equivalent Sets

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3836 Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Total Submission(s): 2890    Accepted Submission(s): 1006 Problem Description To prove two set