codevs 2822 爱在心中

时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
题目描述 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缩点、求强连通分量,重新构图
被其他所有人爱 也就是入度等于强连通分量数-1
间接被爱也需要统计 
我用的是floyd 略慢,大佬们可改进 (大佬们肯定不会路过。。)。
注意图可能不连通 
#include <ctype.h>
#include <cstdio>
#define N 100005

void read(int &x)
{
    x=0;bool f=0;
    register char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    x=f?(~x)+1:x;
}
struct Edge
{
    int next,to;
    Edge (int next=0,int to=0) :next(next),to(to){}
};
struct Edge edge[N<<1];
int Map[300][300],in[N],newhead[N],tim,head[N],num[N],cnt,n,m,dfn[N],low[N],sumcol,col[N],stack[N],top;
bool instack[N],flag;
int min(int a,int b){return a>b?b:a;} 
void tarjan(int x)
{
    low[x]=dfn[x]=++tim;
    instack[x]=1;
    stack[++top]=x;
    for(int u=head[x];u;u=edge[u].next)
    {
        int v=edge[u].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(instack[v]) low[x]=min(low[x],dfn[v]);
    }
    if(low[x]==dfn[x])
    {
        sumcol++;
        int t;
        do
        {
            t=stack[top--];
            instack[t]=false;
            col[t]=sumcol;
            num[sumcol]++;
        }while(t!=x);
    }
}
void rebuild()
{
    for(int i=1;i<=n;i++)
    {
        for(int u=head[i];u;u=edge[u].next)
        {
            int v=edge[u].to;
            if(col[i]!=col[v]&&!Map[col[i]][col[v]])
            {
                Map[col[i]][col[v]]=1;
                in[col[v]]++;
            }
        }
    }
    for(int i=1;i<=sumcol;i++)
    {
        for(int j=1;j<=sumcol;j++)
        {
            for(int k=1;k<=sumcol;k++)
            {
                if(j!=k&&k!=i&&i!=j)
                {
                    if(Map[j][i]&&Map[i][k]&&!Map[j][k])
                    {
                        Map[j][k]=1;
                        in[k]++;
                    }
                }
            }
        }
    }
}
int main()
{
    read(n);
    read(m);
    for(int x,y;m--;)
    {
        read(x);
        read(y);
        edge[++cnt]=Edge(head[x],y);
        head[x]=cnt;
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    int ans=0;
    for(int i=1;i<=sumcol;i++) if(num[i]>1) ans++;
    printf("%d
",ans);
    rebuild();
    for(int i=1;i<=sumcol;i++)
    {
        if(in[i]==sumcol-1&&num[i]>1) 
        {
            for(int j=1;j<=n;j++)
                if(col[j]==i) printf("%d ",j);
            printf("
");
            flag=true;
        }
    }
    if(!flag) printf("-1");
    return 0;
}
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
原文地址:https://www.cnblogs.com/ruojisun/p/7204294.html