HDU 3639 Hawk-and-Chicken【强连通+树形DP】
题意: 有n个人正在玩游戏,完成一个传递的游戏,假如A传递到B,B传递给C,则C拥有2的传递值,C是胜利者,如果C又传递回A,那么A,B,C三者都拥有传递值为2的
胜利者,输出最后获得的最多传递值和拥有该传递值的人。
分析:强连通缩点后用树形DFS找到最大值。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define clr(x) memset(x,0,sizeof(x)) #define min(a,b)(a)<(b)?(a):(b) #define max(a,b)(a)>(b)?(a):(b) #define maxn 5005 struct node { int to,next; }e[1000000],edge[1000000]; int tt; int tot; int head[maxn]; int sh[maxn]; void add(int s, int t) { e[tot].to = t; e[tot].next = head[s]; head[s] = tot++; } void add2(int s,int t) { edge[tt].to = t; edge[tt].next = sh[s]; sh[s] = tt++; } int dfn[maxn]; int low[maxn]; int sta[maxn]; int ins[maxn]; int col[maxn]; int ind[maxn]; int val[maxn]; int v[maxn]; int dp[maxn]; int sn,ti,top; void tarjan(int u) { dfn[u]=low[u]=++ti; sta[++top]=u; ins[u]=1; int i,k; for(i=head[u];i;i=e[i].next) { k=e[i].to; if(dfn[k]==0) { tarjan(k); if(low[k]<low[u]) low[u]=low[k]; } else if(ins[k]) low[u]=min(low[u],dfn[k]); } if(dfn[u] == low[u]) { sn++; do { k = sta[top--]; ins[k] = 0; col[k] = sn; val[sn]++; }while(k!=u); } } int sum; void dfs(int u) { v[u] = 1; int i,k; int s = val[u]; for(i = sh[u]; i;i = edge[i].next){ k = edge[i].to; if(dp[k]==-1) dfs(k); s+=dp[k]; } dp[u] = s; } int num[maxn]; int res[maxn]; int main() { int ca=1,t,n,m; int i,j,k; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); int a,b; tot=1; clr(head); while(m--){ scanf("%d %d",&a,&b); add(a, b); } clr(dfn); clr(col); clr(val); top=sn=ti=0; for(i = 0; i < n; ++i) if(dfn[i] == 0) tarjan(i); clr(sh); clr(ind); tt=1; for(i = 0; i < n; ++i) for(j = head[i]; j; j = e[j].next){ k = e[j].to; if(col[i] != col[k]){ add2(col[k], col[i]); ind[col[i]]++; } } int r=0; int xu; int top=0; memset(dp,-1,sizeof(dp)); clr(v); for(i = 1; i <= sn; ++i) if(ind[i] == 0){ dfs(i); if(dp[i] >= r){ r = dp[i]; num[i] = r; } } printf("Case %d: %d\n",ca++,r-1); for(i = 0; i < n; ++i) if(num[col[i]] == r ){ printf("%d",i); break; } for( ++i; i < n; ++i) if(num[col[i]] == r){ printf(" %d",i); } printf("\n"); } return 0; }