HDU3639 Hawk-and-Chicken Tarjan縮點 +dfs+貪心

HDU3639 Hawk-and-Chicken :Tarjan縮點 +dfs+貪心

Description

一個N(0~n-1)個點與M條邊的有向圖,他們是有傳遞關係的,問對於圖中哪些點是其他最多點能到達他的。

Input

第一行一個T,表示T組測試數據.
每組數據第一行爲N,M
後面M行爲兩個正整數A,B,代表A到B有一條有向邊.

Output

對應每組數據輸出若干個答案.

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

HINT

題解

可以先縮點,再建一個每個連通塊的反向圖,這樣最多的點肯定是出度爲0的點。很容易證明。
如果假設最大值存在於一個入度不爲0的分量中,那麼連接這個分量的 那個分量票數支持肯定大於這個分量,假設不成立。
用dfs逐個搜索一遍就可以。

#include <cstdio>
#include <iostream>
#include <cmath>
#include <stack>
#include <algorithm>
#include <cstring>
#include <climits>
#include<vector>
#define MAXN 7000
#define MAXM 60000+10
#define M(x) memset(x,0,sizeof(x))
using namespace std;
int T;
struct Edge{
    int next,from,to,tnext;
};
struct G{
    int head[MAXN],num,tail[MAXN];
    Edge edge[MAXM*2];
    void add(int from,int to)
    {
        edge[++num].next=head[from];
        edge[num].tnext=tail[to];
        edge[num].from=from;
        edge[num].to=to;
        head[from]=num;tail[to]=num;
    }
    void e()
    {
        num=0;
        M(head);M(tail);M(edge);
    }
}g1,g2;
int n,m;
int low[MAXN],dfn[MAXN],dfnum,cnt[MAXN],col[MAXN],co,vis[MAXN],vis2[MAXN];
int ans[MAXN],ans2[MAXN],maxn;
vector<int> con[MAXN];
stack<int> st;
void tarjan(int x)
{
    dfn[x]=low[x]=++dfnum;vis[x]=1;st.push(x);
    for(int i=g1.head[x];i;i=g1.edge[i].next)
    {
        if(!dfn[g1.edge[i].to])
        {
            tarjan(g1.edge[i].to);
            low[x]=min(low[x],low[g1.edge[i].to]);
        }else if(vis[g1.edge[i].to]) low[x]=min(low[x],dfn[g1.edge[i].to]);
    }
    if(low[x]==dfn[x])
    {
        int t=1;col[x]=++co;vis[x]=0;
        con[co].push_back(x);
        while(st.top()!=x) 
        {con[co].push_back(st.top());t++;vis[st.top()]=0;col[st.top()]=co;st.pop();}
        st.pop();cnt[co]=t;
    }
}
int cu[MAXN];
int dfs(int x)
{   
    vis2[x]=1;
    int sum=0;
    for(int i=g2.tail[x];i;i=g2.edge[i].tnext)
    if(!vis2[g2.edge[i].from])
    {   
        sum+=cnt[g2.edge[i].from]+
        dfs(g2.edge[i].from);
    }
    return sum;
}
void init()
{
    maxn=co=dfnum=0;
    g1.e();g2.e();M(ans);M(ans2);M(cnt);M(col);
    M(con);M(vis);M(vis2);M(low);M(dfn);M(cu);
    while(st.size()) st.pop();
}
int main()
{
    scanf("%d",&T);
    for(int o=1;o<=T;o++)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {   
            int x,y;
            scanf("%d%d",&x,&y);
            g1.add(x+1,y+1);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        for(int i=1;i<=m;i++)
        {   
            if(col[g1.edge[i].from]!=col[g1.edge[i].to])
                g2.add(col[g1.edge[i].from],col[g1.edge[i].to]),
                cu[col[g1.edge[i].from]]++;
        }
        for(int i=1;i<=co;i++)
        {   
            if(!cu[i])
            {M(vis2);ans2[i]=dfs(i)+cnt[i]-1;maxn=max(maxn,ans2[i]);}
        }

        for(int i=1;i<=co;i++)
        {   
            if(ans2[i]==maxn)
            for(int j=0;j<cnt[i];j++) ans[++ans[0]]=con[i][j];
        }
        sort(ans+1,ans+ans[0]+1);
        printf("Case %d: %d\n",o,maxn);
        printf("%d",ans[1]-1);
        for(int i=2;i<=ans[0];i++)
        printf(" %d",ans[i]-1);
        printf("\n");
    }
    return 0;
}
發佈了50 篇原創文章 · 獲贊 4 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章