题目描述 Description
“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”
在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。
输入描述 Input Description
第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。
第2到第M+1行,每行两个数A、B,代表A爱B。
输出描述 Output Description
第1行,一个数,代表爱的国度里有多少爱心天使。
第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。
样例输入 Sample Input
样例输入1:
6 7
1 2
2 3
3 2
4 2
4 5
5 6
6 4
样例输入2:3 3
1 2
2 1
2 3
样例输出 Sample Output
样例输出1:
2
2 3样例输出2:
1
-1
数据范围及提示 Data Size & Hint
各个测试点1s
题解
强连通分量,缩点例题。题目没讲清楚数据范围,n<=10000,m<=50000可过。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,zz,head[10002],h[10002];
struct bian
{int to,nx;} e[50002],tr[50002];
int pre[10002],low[10002],sccnum[10002],scc,cont;
int stack[10002],top;
int have[10002];
void dfs(int x)
{
//printf("%d\n",x);
pre[x]=low[x]=++cont;
stack[++top]=x;
int i=head[x];
while(i)
{int p=e[i].to;
if(!pre[p])
{dfs(p); low[x]=min(low[x],low[p]);}
else if(!sccnum[p])
low[x]=min(low[x],pre[p]);
i=e[i].nx;
}
int p=-1;
if(pre[x]==low[x])
{scc++;
while(p!=x)
{p=stack[top]; top--;
sccnum[p]=scc;
have[scc]++;
}
}
}
void tarjan()
{
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++)
{if(!pre[i]) dfs(i);}
//cout<<1<<endl<<endl;
/*for(int i=1;i<=n;i++) printf("%d %d\n",i,sccnum[i]);
printf("\n");*/
}
void rebuild()
{
for(int i=1;i<=n;i++)
{int p=head[i];
while(p)
{if(sccnum[i]!=sccnum[e[p].to])
{tr[++zz].to=sccnum[e[p].to];
tr[zz].nx=h[sccnum[i]];
h[sccnum[i]]=zz;
}
p=e[p].nx;
}
}
//for(int i=1;i<=scc;i++) printf("%d\n",h[i]);
//for(int i=1;i<=zz;i++) printf("%d %d\n",tr[i].to,tr[i].nx);
}
void find()
{
int ans=0;
for(int i=1;i<=scc;i++)
{if(have[i]>1) ans++;}
printf("%d\n",ans);
ans=-1;
for(int i=1;i<=scc;i++)
{if(!h[i])
{if(ans!=-1||have[i]==1)
{ans=-1;break;}
else ans=i;
}
}
if(ans==-1) printf("%d\n",ans);
else
{for(int i=1;i<=n;i++)
{if(sccnum[i]==ans) printf("%d ",i);}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{int a,b;
scanf("%d%d",&a,&b);
e[i].to=b; e[i].nx=head[a]; head[a]=i;
}
tarjan();
//for(int i=1;i<=scc;i++) printf("%d %d\n",i,have[i]);
rebuild();
find();
return 0;
}