• 爱在心中


    时间限制: 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

    思路:Tarjan

    代码实现:

     1 #include<cstdio>
     2 #include<cstring>
     3 const int maxn=1e4+10;
     4 const int maxm=1e5+10;
     5 inline int min_(int x,int y){return x<y?x:y;}
     6 int n,m,pro,ans,angel;
     7 int a,b;
     8 int h[maxn],hs;
     9 int e_q[maxm],e_z[maxm],e_n[maxm];
    10 int dn[maxn],fl[maxn],st[maxn],dns,top;
    11 int color[maxn],num[maxn],cd[maxn],cs;
    12 bool v[maxn];
    13 void tarjan(int k){
    14     dn[k]=fl[k]=++dns;
    15     st[++top]=k,v[k]=true;
    16     for(int i=h[k];i;i=e_n[i]){
    17         if(!dn[e_z[i]]){
    18             tarjan(e_z[i]);
    19             fl[k]=min_(fl[k],fl[e_z[i]]);
    20         }
    21         if(v[e_z[i]]) fl[k]=min_(fl[k],dn[e_z[i]]);
    22     }
    23     if(dn[k]==fl[k]){
    24         cs++;
    25         while(st[top+1]!=k){
    26             color[st[top]]=cs;
    27             v[st[top--]]=0;
    28             num[cs]++;
    29         }
    30     }
    31 }
    32 int main(){
    33     scanf("%d%d",&n,&m);
    34     for(int i=1;i<=m;i++){
    35         scanf("%d%d",&a,&b);
    36         ++hs,e_q[hs]=a,e_z[hs]=b,e_n[hs]=h[a],h[a]=hs;
    37     }
    38     for(int i=1;i<=n;i++) if(!dn[i]) tarjan(i);
    39     for(int i=1;i<=m;i++) if(color[e_q[i]]!=color[e_z[i]]) ++cd[color[e_q[i]]];
    40     for(int i=1;i<=cs;i++) if(!cd[i]) ans=i,pro++;
    41     for(int i=1;i<=cs;i++) if(num[i]>1) angel++;
    42     printf("%d
    ",angel);
    43     if(pro==1&&num[ans]>1){for(int i=1;i<=n;i++) if(color[i]==ans) printf("%d ",i);}
    44     else puts("-1");
    45     return 0;
    46 }

    缩点后,唯一一个出度为零的点,如果是点集的话,就是传说中的最受欢迎的爱心天使了。

  • 相关阅读:
    [CF603C] Lieges of Legendre
    [CF1070A] Find a Number
    [CF431D] Random Task
    2020牛客暑期多校训练营(第二场)C
    2020牛客暑期多校训练营(第二场)F
    2020牛客暑期多校训练营(第二场)D
    2020牛客暑期多校训练营(第一场)H
    [CF1000E] We Need More Bosses
    Java学习2 (ThreadLocal)
    Java复习1
  • 原文地址:https://www.cnblogs.com/J-william/p/6751719.html
Copyright © 2020-2023  润新知