hdu3639 Hawk-and-Chicken【强连通】

来源:互联网 发布:程序员 转行 投资 编辑:程序博客网 时间:2024/06/06 12:30

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3639
题意:有n个小朋友要做游戏,但是需要选一个Hawk出来,老师决定让小朋友通过投票的方式来选举这个扮演者,每个小朋友都有一个手帕,代表支持一个人(其实手帕没卵用),把他理解为支持就好了,支持具有传递性,比如A支持B,B支持C,那么C就有两个人支持了,于是在一个强连通里面,每个人都有v-1个人支持,现在为你谁的支持数最多,输出这个人的编号(0~n-1)和支持数
解析:首先强连通缩点,每个点的价值就是这个连通块里的节点数,如果对于缩点完后的图来说,最大值一定是出度为零的点,但是,出度为零的点不一定是答案,所以为了便于计算最大票数,那么就采用反向建图,dfs入度为零的点,然后维护最大值,最后输出答案即可

#include <bits/stdc++.h>using namespace std;const int maxn = 5005;vector<int>G[maxn];vector<int>rG[maxn];vector<int>G2[maxn];vector<int>vs;int cmp[maxn],vis[maxn];int in[maxn],cnt[maxn],ans[maxn];void init(int n){    for(int i=0;i<n;i++)    {        G[i].clear();        rG[i].clear();        G2[i].clear();    }}void addEdge(int from,int to){    G[from].push_back(to);    rG[to].push_back(from);}void dfs(int u){    vis[u] = 1;    for(int i=0;i<(int)G[u].size();i++)    {        int v = G[u][i];        if(!vis[v])            dfs(v);    }    vs.push_back(u);}void rdfs(int u,int k){    vis[u] = 1;    cmp[u] = k;    for(int i=0;i<(int)rG[u].size();i++)    {        int v = rG[u][i];        if(!vis[v])            rdfs(v,k);    }}int scc(int n){    memset(vis,0,sizeof(vis));    vs.clear();    for(int i=0;i<n;i++)    {        if(!vis[i])            dfs(i);    }    memset(vis,0,sizeof(vis));    int k = 0;    for(int i=n-1;i>=0;i--)    {        if(!vis[vs[i]])            rdfs(vs[i],k++);    }    return k;}int dfs1(int u){    int sum = 0;    vis[u] = 1;    for(int i=0;i<(int)G2[u].size();i++)    {        int v = G2[u][i];        if(!vis[v])            sum += cnt[v]+dfs1(v);    }    return sum;}void slove(int n,int case_t){    int k = scc(n);    memset(in,0,sizeof(in));    memset(cnt,0,sizeof(cnt));    memset(ans,0,sizeof(ans));    for(int i=0;i<n;i++)    {        cnt[cmp[i]]++;        for(int j=0;j<(int)rG[i].size();j++)        {            int v = rG[i][j];            if(cmp[i]!=cmp[v])            {                in[cmp[v]]++;                G2[cmp[i]].push_back(cmp[v]);            }        }    }    int res = 0;    for(int i=0;i<k;i++)    {        if(in[i]==0)        {            memset(vis,0,sizeof(vis));            int tt = dfs1(i);            ans[i] = cnt[i]-1+tt;            res = max(ans[i],res);        }    }    int first = 0;    printf("Case %d: %d\n",case_t,res);    for(int i=0;i<n;i++)    {        if(ans[cmp[i]]==res)        {            if(first)                printf(" %d",i);            else            {                first = 1;                printf("%d",i);            }        }    }    puts("");}int main(void){    int t,case_t = 1;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d %d",&n,&m);        init(n);        for(int i=0;i<m;i++)        {            int x,y;            scanf("%d %d",&x,&y);            addEdge(x,y);        }        slove(n,case_t++);    }    return 0;}
原创粉丝点击