题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3639
题解:将强连通分量缩成一个点,反向建图,对每个入度为0的点DFS,找出最大值即可。
#include <cstdio> #include <cstring> #include <vector> #define MAXN 5001 using namespace std; struct node { int to,next; }edge[30001]; vector<int>mp[MAXN]; int belong[MAXN],num[MAXN],maxans[MAXN]; int head[MAXN],instack[MAXN],low[MAXN],dfn[MAXN]; int stack[MAXN],tot,Dindex,top,Bcnt,n,indegree[MAXN]; void Init(int n) {//初始化 int i; tot=0,top=0,Dindex=0,Bcnt=0; memset(head,-1,sizeof(head)); memset(instack,0,sizeof(instack)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(belong,0,sizeof(belong)); memset(num,0,sizeof(num)); memset(indegree,0,sizeof(indegree)); memset(maxans,0,sizeof(maxans)); for(i=0;i<=n;++i) mp[i].clear(); } void addEdge(int from,int to) { edge[tot].to=to; edge[tot].next=head[from]; head[from]=tot++; } int Scan() { char ch; int ret=0; while((ch=getchar())<'0'||ch>'9'); while(ch>='0'&&ch<='9') { ret=ret*10+(ch-'0'); ch=getchar(); } return ret; } void Tarjan(int x) { int i,u,v; dfn[x]=low[x]=++Dindex;//时间戳 stack[top++]=x; instack[x]=1; for(i=head[x];i!=-1;i=edge[i].next) { u=edge[i].to; if(!dfn[u]) { Tarjan(u); low[x]=low[x]>low[u]?low[u]:low[x]; } else if(instack[u]&&low[x]>dfn[u]) low[x]=dfn[u]; } if(low[x]==dfn[x]) { //Bcnt++; do { v=stack[--top]; instack[v]=0; belong[v]=Bcnt; num[Bcnt]++;//保存该强连通分量的点数 } while (v!=x); Bcnt++; } } void DFS(int x) { instack[x]=1; tot+=num[x]; for(int i=0;i<mp[x].size();++i) { if(!instack[mp[x][i]]) DFS(mp[x][i]); } return ; } int main() { int m,test,i,j,x,Max,cases=1; scanf("%d",&test); while(test--) { n=Scan(); m=Scan(); Init(n); while(m--) { i=Scan(); j=Scan(); // i++,j++; addEdge(i,j); } for(i=0;i<n;++i) { if(!dfn[i]) Tarjan(i); } for(i=0;i<n;++i) { for(j=head[i];j!=-1;j=edge[j].next) { x=edge[j].to; if(belong[i]!=belong[x]) //不在同一个连通分量的点 { mp[belong[x]].push_back(belong[i]); indegree[belong[i]]++; } } } Max=-1; for(i=0;i<Bcnt;++i) { tot=0; if(indegree[i]==0) { memset(instack,0,sizeof(instack)); DFS(i); maxans[i]=tot;//保存每一个入度为0的最大值 Max=Max<tot?tot:Max; } } printf("Case %d: %d\n",cases++,Max-1); x=0; for(i=0;i<n;++i) { if(maxans[belong[i]]==Max) { if(!x) { printf("%d",i); x=1; } else printf(" %d",i); } } printf("\n"); } return 0; }