1. 程式人生 > >Luogu P2341 [HAOI2006]受歡迎的牛

Luogu P2341 [HAOI2006]受歡迎的牛

text 沒有 ++ pri str %d 通過 存在 ||

P2341 [HAOI2006]受歡迎的牛

題目大意

題面已經說的夠明白了

我只是為了多一個標題,走走過場,好看QwQ

思路

題目是明去給出的條件足夠。既然牛的愛慕關系可以傳遞,那麽自然地就想到了連通分量嘍。只要是在同一個連通分量內的牛,它們對整個局面造成的影響是一致的。那麽就可以通過Tarjan算法進行縮點。所點後統計每個強連通分量的出度。如果只有一個出度為零的強連通分量(註意是強連通分量),那麽這個點就是受歡迎的牛。如果存在兩個以上的話,就證明它倆個都沒有互相愛慕,那麽肯定就不存在受歡迎的牛,所以直接輸出0

吐槽一下

woc,Tarjan寫錯了都能剛出85分來,學到了學到了,我之前交的時候++Index寫成了Index++。。。遛了遛了

代碼

#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>

const int maxnode = 1e4+3;
const int maxedge = 5e4+3;

using namespace std;

stack<int> S;
int n, m, first[maxnode], next[maxedge], u[maxedge], v[maxedge], num[maxnode];
int
low[maxnode], dfn[maxnode], Index, cnt, in[maxnode], Indgr[maxnode]; bool vis[maxnode]; inline int readInt() { int x = 0, f = 1; char c = getchar(); while (c < 0 || c > 9) { if(c == -) f = -1; c = getchar(); } while (c <= 9 && c >=
0) { x = x*10 + c-0; c = getchar(); } return x * f; } inline void addedge(int f, int i) { next[i] = first[f]; first[f] = i; } inline void Tarjan(int x) { low[x] = dfn[x] = ++Index; vis[x] = 1; S.push(x); int k = first[x]; while (k != -1) { if(!dfn[v[k]]) { Tarjan(v[k]); low[x] = min(low[x], low[v[k]]); } else if(vis[v[k]]) { low[x] = min(low[x], dfn[v[k]]); } k = next[k]; } if(dfn[x] == low[x]) { cnt++; while (!S.empty()) { int temp = S.top(); S.pop(); vis[temp] = 0; in[temp] = cnt; num[cnt]++; if(temp == x) break; } } } int main() { n = readInt(), m = readInt(); memset(first, -1, sizeof(first)); for(int i=1; i<=m; i++) { u[i] = readInt(); v[i] = readInt(); addedge(u[i], i); } for(int i=1; i<=n; i++) { if(!dfn[i]) Tarjan(i); } for(int i=1; i<=n; i++) { int k = first[i]; while (k != -1) { if(in[v[k]] != in[u[k]]) Indgr[in[u[k]]]++; k = next[k]; } } int mark = 0; for(int i=1; i<=cnt; i++) { if(Indgr[i] == 0) { if(mark) { printf("0\n"); return 0; } mark = i; } } printf("%d", num[mark]); }

Luogu P2341 [HAOI2006]受歡迎的牛