HDU 3639 Hawk-and-Chicken (strongly connected component + tree DP), hdudp
Address: HDU 3639
First, scale down the point of the strongly connected component, contract the point, and then re-follow the reverse structure of the block after the contraction point. The value of each block is the number of points reduced inside, then, the largest part of the votes to be obtained must be the block with a degree of 0 after the re-composition, and then the maximum value can be obtained.
The Code is as follows:
#include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>using namespace std;#define LL long long#define pi acos(-1.0)const int mod=1e9+7;const int INF=0x3f3f3f3f;const double eqs=1e-9;const int MAXN=5000+10;const int MAXM=30000+10;int head[MAXN], cnt, low[MAXN], dfn[MAXN], belong[MAXN], instack[MAXN], stk[MAXN], dp[MAXN];int ans, indx, top;struct node{ int u, v, next;}edge[MAXM];void add(int u, int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++;}void tarjan(int u){ low[u]=dfn[u]=++indx; instack[u]=1; stk[++top]=u; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]){ low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]){ ans++; while(1){ int v=stk[top--]; belong[v]=ans; dp[ans]++; instack[v]=0; if(u==v) break; } }}void init(){ memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); memset(dp,0,sizeof(dp)); cnt=ans=indx=top=0;}int head1[MAXN], cnt1, vis[MAXN], in[MAXN], max1, sum;struct node1{ int u, v, next;}edge1[MAXM];void add1(int u, int v){ edge1[cnt1].v=v; edge1[cnt1].next=head1[u]; head1[u]=cnt1++;}void dfs(int u){ vis[u]=1; sum+=dp[u]; for(int i=head1[u];i!=-1;i=edge1[i].next){ int v=edge1[i].v; if(!vis[v]){ dfs(v); } }}void init1(){ memset(head1,-1,sizeof(head1)); memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); cnt1=0; max1=0;}int c[MAXN], tot, d[MAXN];int main(){ int t, n, m, i, j, u, v, Case=0; scanf("%d",&t); while(t--){ Case++; scanf("%d%d",&n,&m); init(); while(m--){ scanf("%d%d",&u,&v); add(u,v); } for(i=0;i<n;i++){ if(!dfn[i]) tarjan(i); } init1(); for(i=0;i<n;i++){ for(j=head[i];j!=-1;j=edge[j].next){ if(belong[i]!=belong[edge[j].v]){ add1(belong[edge[j].v],belong[i]); in[belong[i]]++; } } } memset(d,-1,sizeof(d)); for(i=1;i<=ans;i++){ if(!in[i]){ sum=0; memset(vis,0,sizeof(vis)); dfs(i); d[i]=sum; max1=max(max1,d[i]); } } tot=0; for(i=0;i<n;i++){ if(d[belong[i]]==max1) c[tot++]=i; } printf("Case %d: %d\n",Case, max1-1); for(i=0;i<tot;i++){ printf("%d",c[i]); if(i!=tot-1) printf(" "); } puts(""); } return 0;}