[CODEVS2882] 爱在心中

Posted zzh-brim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CODEVS2882] 爱在心中相关的知识,希望对你有一定的参考价值。

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

数据范围及提示 Data Size & Hint

各个测试点1s

 


 

 

提交地址 :CODEVS2882

 


 

 

题解:

一道缩点好题。

我们先把图中间的强联通分量找出来然后缩点,最后剩下几个点就有几个天使;

然而并不是,因为题目里又说没有人能够自爱, 所以最后缩完点的每个点的size如果==1的话,就是不合题意的,要去掉这些点;

第二问随便搞搞就行了。

 

首先,因为特殊天使必须是出度为0的点,因为如果她有出度,又因为她是天使,所以她爱的人一定爱她,那么这个特殊天使还得加一个人,就不成立了。

 

而且这样的点只能有一个,因为如果有两个出度为零的点,就不能做到“所有人和天使都爱特殊天使”这个条件,所以,只有当图中只有一个出度为0的天使时,才会产生特殊天使——也就是这个天使。

 


 

 

Code:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 using namespace std;
 5 
 6 int n, m;
 7 
 8 struct edge
 9 {
10     int nxt;
11     int from;
12     int to;
13 }ed[50010];
14 int dfn[10010], low[10010], head[10010];
15 int stack[100010], ins[10010], c[10010];
16 vector <int> scc[10010];
17 int cnt, tot, num, top;
18 
19 inline void add(int x, int y)
20 {
21     cnt++;
22     ed[cnt].nxt = head[x];
23     ed[cnt].from = x;
24     ed[cnt].to = y;
25     head[x] = cnt;
26 }
27 
28 inline void Tarjan(int x)
29 {
30     dfn[x] = low[x] = ++num;
31     stack[++top] = x, ins[x] = 1;
32     for (register int i = head[x] ; i ; i = ed[i].nxt)
33     {
34         int to = ed[i].to;
35         if (!dfn[to])
36         {
37             Tarjan(to);
38             low[x] = min(low[x], low[to]);
39         }
40         else if (ins[to]) 
41             low[x] = min(low[x], low[to]);
42     }    
43     if (dfn[x] == low[x])
44     {
45         tot++;
46         int y;        
47         do{
48             y = stack[top--], ins[y] = 0;
49             c[y] = tot, scc[tot].push_back(y);
50         }while (x != y);
51     }
52     
53 }
54 
55 int du[10010], gr, now;
56 int ans;
57 
58 int main()
59 {
60     scanf("%d%d", &n, &m);
61     
62     for (register int i = 1 ; i <= m ; i ++)
63     {
64         int x, y;
65         scanf("%d%d", &x, &y);
66         add(x, y);
67     }
68     
69     for (register int i = 1 ; i <= n ; i ++) 
70         if (!dfn[i]) Tarjan(i);
71     
72     for (register int i = 1 ; i <= m ; i ++)
73     {
74         if (c[ed[i].from] != c[ed[i].to]) du[c[ed[i].from]]++;
75     }
76     
77     for (register int i = 1 ; i <= tot ; i ++)
78     {
79         if (scc[i].size() > 1) ans++;
80         if (du[i] == 0) now = i, gr++;
81     }
82     printf("%d\n", ans);
83     if (gr == 1 and scc[now].size() > 1)
84     {
85         for (register int i = 1 ; i <= n ; i ++)
86         {
87             if (c[i] == now) printf("%d ", i);
88         }
89         return 0;
90     }
91     puts("-1");
92     return 0;
93 }

 

 

以上是关于[CODEVS2882] 爱在心中的主要内容,如果未能解决你的问题,请参考以下文章

codevs2822爱在心中

codevs2822爱在心中

codevs 2822 爱在心中 tarjan(强联通分量)

codevs 2822 爱在心中

[CodeVS2822]爱在心中

强连通分量——爱在心中(codevs_2822)——tarjan求scc