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;

}

 

 

你可能感兴趣的:(tar)