题意:
有n个小朋友在一个班级中,现在要选择班长。收集了小朋友们的意见,一条意见表示为A认为B合适。这个是具备传递性的,A认为B合适,B认为C合适。那么A也会认为C合适。
现在需要提供一份候选人名单,这里面的人,是被最多的人,认为合适的。
分析:
用tarjan进行缩点,一个强连通分量里面的每个值都是相等的,最大就是在出度为零的点上,所以只需统计出度为零的点上谁的值最大,当然直接统计不好办,所以用反向建图,从出度为0的点向根节点进行遍历再进行统计,比较每个的最大值并进行输出。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e3+10;
const int maxm=3e4+10;
struct node{
int to,next;
}edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],sta[maxn],belong[maxn];
int index,top;
int scc; //强连通分量的个数。
bool instack[maxn];
int num[maxn]; //各个强连通分量所包含的点数。
void addedge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
vector<int> vec[maxn];
void tarjan(int u){
int v;
low[u]=dfn[u]=++index;
sta[top++]=u;
instack[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(!dfn[v]){
tarjan(v);
if(low[u]>low[v]) low[u]=low[v];
}else if(instack[v]&&low[u]>dfn[v]){
low[u]=dfn[v];
}
}
if(low[u]==dfn[u]){
scc++;
do{
v=sta[--top];
instack[v]=false;
belong[v]=scc;
num[scc]++;
}while(v!=u);
}
}
void init(){
scc=top=tot=index=0;
memset(head,-1,sizeof head);
memset(dfn,0,sizeof dfn);
memset(instack,0,sizeof instack);
memset(num,0,sizeof num);
}
int du[maxn];
bool vis[maxn];
int sum;
void dfs(int u){
vis[u]=1;
sum+=num[u];
for(int i=0;i<vec[u].size();i++){
if(!vis[vec[u][i]]){
dfs(vec[u][i]);
}
}
}
int ans[maxn];
int main(){
int T;
scanf("%d",&T);
for(int cs=1;cs<=T;cs++){
int n,m;
scanf("%d%d",&n,&m);
init();
while(m--){
int u,v;
scanf("%d%d",&u,&v);
u++;v++;
addedge(u,v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i=1;i<=scc;i++) vec[i].clear();
memset(du,0,sizeof du);
for(int u=1;u<=n;u++){
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
int uu=belong[u],vv=belong[v];
if(uu!=vv){
vec[vv].push_back(uu);
du[uu]++;
}
}
}
int mx=-1;
memset(ans,-1,sizeof ans);
for(int i=1;i<=scc;i++){
if(du[i]==0){
memset(vis,0,sizeof vis);
sum=0;
dfs(i);
ans[i]=sum-1;
mx=max(sum-1,mx);
}
}
printf("Case %d: %d\n",cs,mx);
bool flag=false;
for(int i=1;i<=n;i++){
if(ans[belong[i]]==mx){
if(!flag) printf("%d",i-1);
else printf(" %d",i-1);
flag=1;
}
}
printf("\n");
}
return 0;
}