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

题意:

有n个人玩老鹰捉小鸡游戏,每个人都像当老鹰,于是他们决定投票选举,每个人都有一票,不可以投自己。票具有传递性假设A投给了B,B有又给了C则C就会得到两票。求得到票数最多的票数及每个人的编号(0-n-1)

思路:
其实划一划图就会发现,每个人得到的票数即为能够到达该点点数,中间可能存在环。如果五环的话,我们只要倒着建图,然后找出入度为0的点,搜索他能到达的点的个数即为该点所得到的票数,因为最优值一定在入度为0的点上。 如果存在环的话,我们只需要通过tarjan缩点,改环所能提供的票数为该环内的点数。然后再重新倒着建图就好了。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 30007
#define N 5007

using namespace std;

const int inf = 100000007;
const int mod = 1000000007;

struct node
{
    int u,v;
    int next;
}g1[M],g2[M];
int head1[N],head2[N];
int ct1,ct2;

int low[N],dfn[N];
int belong[N];
int idx,top,cnt;
bool isn[N];
int vt[N],no[N];
int stk[N];
int val[N];
int ind[N];
int n,m;

void add1(int u,int v)
{
    g1[ct1].v = v;
    g1[ct1].next = head1[u];
    head1[u] = ct1++;
}
void add2(int u,int v)
{
    g2[ct2].v = v;
    g2[ct2].next = head2[u];
    head2[u] = ct2++;
}

void tarjan(int u)
{
    low[u] = dfn[u] = ++idx;
    isn[u] = true; stk[++top] = u;
    for (int i = head1[u]; i != -1; i = g1[i].next)
    {
        int v = g1[i].v;
        if (!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else if (isn[v])
        {
            low[u] = min(low[u],dfn[v]);
        }
    }
    int j;
    if (low[u] == dfn[u])
    {
        cnt++;
        do
        {
            j = stk[top--];
            isn[j] = false;
            belong[j] = cnt;
        }while (j != u);
    }
}
void dfs(int u,int mk)
{
    for (int i = head2[u]; i != -1; i = g2[i].next)
    {
        int v = g2[i].v;
        if (vt[v] != mk)
        {
            no[mk] += val[v];
            vt[v] = mk;
            dfs(v,mk);
        }
    }
}
int main()
{
//    Read();
    int i,j,T;
    int cas = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        CL(head1,-1); ct1 = 0;
        int x,y;
        for (i = 0; i < m; ++i)
        {
            scanf("%d%d",&x,&y);
            x++; y++;
            add1(x,y);
        }
        CL(dfn,0); CL(low,0);
        CL(isn,false);
        idx = top = cnt = 0;
        for (i = 1; i <= n; ++i)
        {
            if (!dfn[i])
            {
                tarjan(i);
            }
        }
        CL(val,0);
        for (i = 1; i <= n;++i) val[belong[i]]++;

        CL(head2,-1); ct2 = 0;
        CL(ind,0);
        for (i = 1; i <= n; ++i)
        {
            for (j = head1[i]; j != -1; j = g1[j].next)
            {
                int v = g1[j].v;
                if (belong[v] != belong[i])
                {
                    add2(belong[v],belong[i]);
                    ind[belong[i]]++;
                }
            }
        }

        CL(no,0);
        int ans = 0;
        for (i = 1; i <= cnt; ++i)
        {
             CL(vt,0);
            if (ind[i] == 0)
            {
                no[i] = val[i] - 1;
                vt[i] = i;
                dfs(i,i);
                ans = max(ans,no[i]);
            }
        }

        printf("Case %d: %d\n",cas++,ans);
        bool flag = false;
        for (i = 1; i <= n; ++i)
        {
            if (no[belong[i]] == ans)
            {
                if (!flag) flag = true;
                else printf(" ");
                printf("%d",i - 1);
            }
        }
        printf("\n");
    }
    return 0;
}

 

 

posted @ 2013-05-10 08:27  E_star  阅读(252)  评论(0编辑  收藏  举报