[CODEVS2882] 愛在心中
“每個人都擁有一個夢,即使彼此不相同,能夠與你分享,無論失敗成功都會感動。愛因為在心中,平凡而不平庸,世界就像迷宮,卻又讓我們此刻相逢Our Home。”
在愛的國度裏有N個人,在他們的心中都有著一個愛的名單,上面記載著他所愛的人(不會出現自愛的情況)。愛是具有傳遞性的,即如果A愛B,B愛C,則A也愛C。
如果有這樣一部分人,他們彼此都相愛,則他們就超越了一切的限制,用集體的愛化身成為一個愛心天使。
現在,我們想知道在這個愛的國度裏會出現多少愛心天使。而且,如果某個愛心天使被其他所有人或愛心天使所愛則請輸出這個愛心天使是由哪些人構成的,否則輸出-1。
第1行,兩個數N、M,代表愛的國度裏有N個人,愛的關系有M條。
第2到第M+1行,每行兩個數A、B,代表A愛B。
第1行,一個數,代表愛的國度裏有多少愛心天使。
第2行,如果某個愛心天使被其他所有人和愛心天使所愛則請輸出這個愛心天使是由哪些人構成的(從小到大排序),否則輸出-1。
樣例輸入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
樣例輸出1:
2
2 3
樣例輸出2:
1
-1
各個測試點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] 愛在心中