• 【codevs2822】爱在心中 tarjan 缩点+理解


    【codevs2822】爱在心中

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

    代码

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <queue>
    #include <typeinfo>
    #include <map>
    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    #define inf 10000000
    inline ll read()
    {
        ll x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    //***************************************************************
    
    struct ss
    {
        int u,to,next;
    } e[50001];
    int out[40001];
    int head[50001],vis[50001],dfn[50001],low[50001],belong[50001],hav[50001];
    int q[50001],inq[50001];
    int t=1,bcnt,cnt,n,m,top;
    void add(int u,int v)
    {
        e[t].to=v;
        e[t].u=u;
        e[t].next=head[u];
        head[u]=t++;
    }
    void dfs(int u)
    {
        vis[u]=inq[u]=1;
        low[u]=dfn[u]=++cnt;
        q[++top]=u;
        for(int i=head[u]; i; i=e[i].next)
        {
            if(!vis[e[i].to])
            {
                dfs(e[i].to);
                low[u]=min(low[u],low[e[i].to]);
            }
            else if(inq[e[i].to])low[u]=min(low[u],dfn[e[i].to]);
        }
        int v=-1;
        if(low[u]==dfn[u])
        {
            bcnt++;
            while(v!=u)
            {
                v=q[top--];
                inq[v]=0;
                belong[v]=bcnt;
                hav[bcnt]++;
            }
        }
    }
    void rebuild()
    {
    
        for(int i=1; i<=m; i++)
        {
            if(belong[e[i].u]!=belong[e[i].to])
            {
                out[belong[e[i].u]]++;
            }
        }
    }
    void tarjan()
    {
        for(int i=1; i<=n; i++)
        {
            if(!vis[i])
            {
                dfs(i);
            }
        }
        rebuild();
    }
    void work()
    {
        int res=0;
        int ans;
        for(int i=1; i<=bcnt; i++)
        {
            if(out[i]==0)
            {
                ans=i;
                res++;
            }
        }
        int bb=0;
        for(int i=1;i<=bcnt;i++)
        {
            if(hav[i]>=2)bb++;
        }
        cout<<bb<<endl;
        if(res==1)
        {
            if(hav[ans]!=1)
            {
                int kk=0;
                int hh[50001];
                for(int i=1; i<=n; i++)
                {
                    if(belong[i]==ans)
                    {
                        hh[++kk]=i;
                    }
                }
                for(int i=1; i<kk; i++)
                {
                    printf("%d ",hh[i]);
                }
                cout<<hh[kk]<<endl;
            }
            else cout<<-1<<endl;
    
        }
        else cout<<-1<<endl;
    }
    int main()
    {
        int u,v;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        tarjan();
        work();
        return 0;
    }
  • 相关阅读:
    android的原理,为什么我们不需要太多的剩余内存(转)
    简单制作RPM二进包实例(转)
    电源相关术语
    Linux 查找指定文件并删除
    Linux内核中的内存屏障(转)
    分压、分流原理
    Linux内核入门—— __attribute__ 机制
    如何手工释放linux内存
    多核编程中的负载平衡难题(转)
    linux2.6.26内核中ARM中断实现详解(转)
  • 原文地址:https://www.cnblogs.com/zxhl/p/4730923.html
Copyright © 2020-2023  润新知