POJ 2186 強連通分量,DAG性質)

2021-08-24 20:40:42 字數 1658 閱讀 6408

description:

給出乙個包含n個點m條邊的有向圖,問其中有多少個點是所有其他點都可達的。

input:

n,m及m條邊

output:

點數analysis:

由於在乙個強連通分量中所有點都互相可達,所以可以先將圖縮點成乙個有向無環圖(dag), 然後有乙個定理是說,在dag中所有點都可達的那個點等價於其中唯一的乙個出度為0的點。

證明:"=>" 若所有點都可達u,則u必然不能達到其他任何點,否則會形成環與dag矛盾, 所以u出度為0

若還存在某個點v,所有點都可達,則表明u也可達v,v同時可達u,形成環矛盾, 所以u唯一

"<="  若u為dag中唯一的乙個出度為0的點,則沿著圖中任何乙個點開始走到最後的任何路徑最後必然停止於u,從而任何一點必然可達u。

任何乙個點往下走到最後必然停止於某個點,否則其中必然形成環,與dag矛盾。

若停止於某個出度不為0的點v, 則還能沿著v的出邊走下去,與停止矛盾,所以必然停在出度為0的u點。

所以有了這個定理後,只要在縮點後的圖中找到了唯一出度為0的點,答案就是該雙聯通分量所含的點數,若沒有唯一出度為0的點則答案為0.

#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define _for(i,a,b) for(int i=(a);i<(b);++i)

#define _rep(i,a,b) for(int i=(a);i<=(b);++i)

typedef long long ll;

const int inf = 1 << 30;

const int mod = 1000000007;

const int maxn = 10005;

int n, m;

int time, idx, dfn[maxn], low[maxn], color[maxn];

stacksta;

vector> g(maxn);

int oud[maxn];

void tarjan(int u)

else if (!color[v])

} if (dfn[u] == low[u]) }}

int main()

time = idx = 0;

memset(dfn, 0, sizeof(dfn));

memset(color, 0, sizeof(color));

for (int i = 1; i <= n; ++i)if (!dfn[i])tarjan(i);

memset(oud, 0, sizeof(oud));

for (int i = 1; i <= n; ++i)

for (int j = 0; j < g[i].size(); ++j)

}int cnt = 0, u;

for (int i = 1; i <= idx; ++i)

int ans = 0;

if (cnt == 1)

printf("%d\n", ans);

} return 0;

}

POJ 2186 強連通分量

比較簡單吧。套模板。gabow include cstdlib include cctype include cstring include cstdio include cmath include algorithm include vector include string include io...

Poj 2186 強連通分量

題目大意 分析題解 個人 view code 1 10180085 perseawe 2186 accepted 1424k 79ms pascal 2645b 2012 05 10 19 54 27 23 var 4 n,m,tot,numofblocks,time,top longint 5 d...

poj2186強連通分量

這題。做了半天,倒是讓我更加了解了強連通分量,是我的第二道強連通。石建讓我做一下這道題,我用模板再變形,改了很久之後,能給出的樣例都過了。discussion上的樣例都過了,倒是上面n多人說資料沒過ac了。你讓我們這資料過了沒ac的生活如何自理。先放著,哪天有思路再來搞。重新做了一遍,發現之前的思路...