hdu 3639 Hawk-and-Chicken
http://acm.hdu.edu.cn/showproblem.php?pid=3639
题意:给一个无向图,求出拥有最多祖父的节点。
思路:先tarjan缩点,可以知道只能出现在叶子节点,所以反向建图,对每个入度为0的节点进行遍历统计。

#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<bitset> #include<stack> #include<utility> using namespace std; const int maxn = 5005; struct nd { int u,v,next; }edge[maxn*10]; int head[maxn],vis[maxn],dfn[maxn],low[maxn],belong[maxn],c[maxn],as[maxn],in[maxn]; stack<int>st; bitset<maxn>Bit; int ecnt,cnt,idx,tot; void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int u) { int i,v; dfn[u] = low[u] = ++idx; vis[u] = 1; st.push(u); for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]){ tarjan(v); low[u] = min(low[v],low[u]); }else if(vis[v]) low[u] = min(dfn[v],low[u]); } if(dfn[u]==low[u]) { ++cnt; do{ v = st.top(); st.pop(); vis[v] = 0; c[cnt]++; belong[v] = cnt; }while(v!=u); } } void dfs(int rt,int u,int sum) { int i,v; if(Bit[u])return; Bit[u] = 1; as[rt] += sum; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; dfs(rt,v,c[v]); } } int main() { int i,j,k,t,n,m,u,v,ans,cas = 0; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(belong,0,sizeof(belong)); memset(c,0,sizeof(c)); memset(as,0,sizeof(as)); memset(in,0,sizeof(in)); memset(head,-1,sizeof(head)); ecnt = cnt = idx = 0; for(i = 0; i < m; ++ i) { scanf("%d %d",&u,&v); add(u,v); } for(i = 0; i < n; ++ i) if(!dfn[i]) tarjan(i); memset(head,-1,sizeof(head)); k = ecnt; ecnt = 0; for(i = 0; i < k; ++ i) { u = belong[edge[i].u]; v = belong[edge[i].v]; if(u!=v){ add(v,u); in[u]++; } } ans = 0; for(i = 1; i <= cnt; ++ i)if(!in[i]) { Bit.reset(); dfs(i,i,c[i]); ans = max(ans,as[i]); } k = 0; for(i = 0; i < n; ++ i) if(as[belong[i]]==ans) c[k++] = i; printf("Case %d: %d\n",++cas,ans-1); for(i = 0; i < k - 1; ++i) printf("%d ",c[i]);printf("%d\n",c[i]); }return 0; }