• CodeVS 2822 爱在心中


    Description

    “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”

    在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
    如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
    现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。

    Input

    第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。

    第2到第M+1行,每行两个数A、B,代表A爱B。
     
    Output
    第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的联通分量的数量;
    第二问的话没有像隔壁wyx那样重新建一次边...而是统计了一下缩点后每个点的出度,因为跑完Tarjan之后是有向无环图,根据题意,第二问的答案必是出度为0且唯一的一个出度为0的点,根据这个可以判断是否有解,当然也要判断一下那个点是不是爱心天使;
    代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<stack>
     5 using namespace std;
     6 
     7 const int maxn = 100000 + 5;
     8 struct Edge {
     9     int f, t;
    10 }gra[maxn];
    11 int n, m, u, dcnt, scnt, out;
    12 int fir[maxn], nxt[maxn], outdeg[maxn];
    13 int dfn[maxn], low[maxn], scc[maxn], sccz[maxn];
    14 stack<int>S;
    15 void Tarjan(int);
    16 
    17 int main()
    18 {
    19     memset(fir, -1, sizeof(fir));
    20     scanf("%d%d", &n, &m);
    21     for(int i = 1; i <= m ; i++) {
    22         int f, t;
    23         scanf("%d%d", &f, &t);
    24         gra[++u] = (Edge){f, t};
    25         nxt[u] = fir[f], fir[f] = u;
    26     }
    27     for(int i = 1; i <= n; i++)
    28         if(!dfn[i]) Tarjan(i);
    29     int ans = 0;
    30     for(int i = 1; i <= scnt; i++)
    31         if(sccz[i] > 1) ans++;
    32     cout << ans << endl;
    33     for(int i = 1; i <= n; i++)
    34         for(int j = fir[i]; ~j; j = nxt[j]) {
    35             int tmp = gra[j].t;
    36             if(scc[i] != scc[tmp]) outdeg[scc[i]]++;
    37         }
    38     ans = 0;
    39     for(int i = 1; i <= scnt; i++)
    40         if(!outdeg[i]) ans = i, out++;
    41     if(out > 1||sccz[ans] <= 1) {
    42         puts("-1");
    43         return 0;
    44     }
    45     for(int i = 1; i <= n; i++)
    46         if(scc[i] == ans) printf("%d ", i);
    47     return 0;
    48 }
    49 
    50 void Tarjan(int k)
    51 {
    52     S.push(k);
    53     dfn[k] = low[k] = ++dcnt;
    54     for(int i = fir[k]; ~i; i = nxt[i]) {
    55         int tmp = gra[i].t;
    56         if(!dfn[tmp]) {
    57             Tarjan(tmp);
    58             low[k] = min(low[k], low[tmp]);
    59         }
    60         else if(!scc[tmp]) low[k] = min(low[k], dfn[tmp]);
    61     }
    62     if(dfn[k] == low[k]) {
    63         scnt++;
    64         while(!S.empty()) {
    65             int tmp = S.top();
    66             S.pop();
    67             scc[tmp] = scnt;
    68             sccz[scnt]++;
    69             if(tmp == k) break;
    70         }
    71     }
    72 }
  • 相关阅读:
    20220803 01. Linux是什么与如何学习
    20220705 MarkText 快捷键
    20220804 02. 主机规划与磁盘分区
    20220807 04. 首次登陆与线上求助
    20220729 正则表达式
    20220802 00. 计算机概论
    QT执行文件打包方法
    c# winform 多线程中ShowDialog()步骤无效的解决办法
    win10笔记本安装 SolidWorks2016软件,SW20102016.Activator.GUI.SSQ激活闪退解决办法
    easymodbus串口模式调试测试
  • 原文地址:https://www.cnblogs.com/DreifxP/p/7763805.html
Copyright © 2020-2023  润新知