【codevs2822】 爱在心中 tarjan+统计点的个数

来源:互联网 发布:jd抢购软件 编辑:程序博客网 时间:2024/05/27 20:50

2822 爱在心中

题目描述 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

题解:一定要读懂题意,用tarjan求出每个强连通分量,判断拥有多少个强连通分量,并且如果这个强连通分量只有一个点那么不能算作爱心天使。最后判断哪个强连通分量被其他所有强连通分量连接,输出其中的点的人的序号(类似于受欢迎的牛),注意排序。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 100006using namespace std;struct node{    int from,to,next;}e[N];int low[N],dfn[N],insex,stack[N],tot;bool instack[N];int e_num,head[N];bool flag[N];int color[N];int n,t,ans,m,anss[N],num[N];int a[N],b[N],ru[N],chu[N];void add(int from,int to){    ++e_num;    e[e_num].from=from;    e[e_num].to=to;    e[e_num].next=head[from];    head[from]=e_num;}void tarjan(int u){    int i;    low[u]=dfn[u]=++insex;    instack[u]=true;    stack[++tot]=u;    for (i=head[u];i;i=e[i].next)    {        int v=e[i].to;        if (!dfn[v])        {            tarjan(v);            low[u]=min(low[v],low[u]);        }        else if (instack[v])        {            low[u]=min(low[u],dfn[v]);        }    }    if (low[u]==dfn[u])    {        int tmp=0;        ++t;        while (tmp!=u)        {            tmp=stack[tot--];            instack[tmp]=false;            color[tmp]=t;            num[t]++;        }    }}void slove(){    int i;    memset(dfn,0,sizeof(dfn));    for (i=1;i<=n;i++)        if (!dfn[i])            tarjan(i);}int main(){    int x,i,y,temp;    scanf("%d%d",&n,&m);    for (i=1;i<=m;i++)    {        scanf("%d%d",&x,&y);        add(x,y);        a[i]=x;b[i]=y;    }    slove();//  for (i=1;i<=n;i++)//      printf("%d ",color[i]);    ans=t;    for (i=1;i<=t;i++)        if (num[i]==1) ans--;     printf("%d\n",ans);    for (i=1;i<=m;i++)        if (color[a[i]]!=color[b[i]])        {            chu[color[a[i]]]++;        }    if (ans==0) {printf("-1");return 0;}    ans=0;    for (i=1;i<=t;i++)    {        if (chu[i]==0) {ans++;temp=i;}    }    if (ans!=1) {printf("-1");return 0;}    ans=0;    t=0;    for (i=1;i<=n;i++)        if (color[i]==temp) {ans++;anss[++t]=i;}    sort(anss+1,anss+t+1);    for (i=1;i<=t;i++)        printf("%d ",anss[i]);}
0 0