爱在心中(强连通分量)

QAQ

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int color[9999],c=0,num=0,low[9999],dfn[9999],top,f[9999],s[9999],fx[9999];
int n,m,ans;
int cnt,head[9999],net[99999],to[99999];
int flag[9999];
void add(int x,int y)
{
    cnt++;
    to[cnt]=y;
    net[cnt]=head[x];
    head[x]=cnt;
} 
void dfs(int x)
{

    dfn[x]=++num;
    low[x]=num;
    f[x]=1;
    s[++top]=x;

    for(int i=head[x];i;i=net[i])
    {
        int tmp=to[i];
        if(dfn[tmp]==0)
        {
            dfs(tmp);
            low[x]=min(low[x],low[tmp]);
        }
        else 
         if(f[tmp]==1)
         {
            low[x]=min(low[x],dfn[tmp]);
         }
    } 

    if(low[x]==dfn[x])
    {
        f[x]=0;
        color[x]=++c;
        int tot=1;
        while(s[top]!=x)
        {
            tot++;
            color[s[top]]=c;
            f[top--]=0;
        } 
        top--;
        if(tot>1) ans++,fx[c]=1;
    }
}
void find()
{

    for(int i=1;i<=n;i++)//枚举所有点
    {
        for(int j=head[i];j;j=net[j])
        {
            int tmp=to[j];//枚举邻接点

            if(color[i]!=color[tmp])//若这个强连通分量有出去的边,就说明这个天使不会被其他全部人所爱
             flag[color[i]]=1;//标记此强连通分量不行
        }
    }

}
int main()
{


    scanf("%d%d",&n,&m);

    for(int i=1;i<=m;i++)
    {
        int x,y;

        scanf("%d%d",&x,&y);

        add(x,y);
    }

    for(int i=1;i<=n;i++)
    if(!dfn[i]) dfs(i);//跑tarjan来求强连通分量

    printf("%d
",ans);

    find();//找有无被其他人全部爱的天使

    int z;
    ans=0;

    for(int i=1;i<=c;i++)
     if(flag[i]==0) z=i,ans++;//找符合条件的强连通分量

    if(ans!=1||fx[z]==0) printf("-1");//如果有不止一个符合条件的强连通分量,那么就不会有一个符合条件的天使
    else
    {
        for(int i=1;i<=n;i++)
         if(color[i]==z) printf("%d ",i);//输出组成这个天使的人
    }
     return 0;
}
原文地址:https://www.cnblogs.com/ht008/p/6819832.html