• 爱在心中(强连通分量)


    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;
    }
  • 相关阅读:
    OI竞赛常见错误总结
    lis最长上升子序列o(nlogn)优化
    链表及其简单应用
    栈及其简单应用
    哈希表Hash:概念与基本操作
    队列及其简单应用
    poj1418 Viva Confetti 判断圆是否可见
    poj1981 Circle and Points 单位圆覆盖问题
    poj2187 Beauty Contest(旋转卡壳)
    poj2932 Coneology (扫描线)
  • 原文地址:https://www.cnblogs.com/ht008/p/6819832.html
Copyright © 2020-2023  润新知