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的生活如何自理。先放著,哪天有思路再來搞。重新做了一遍,發現之前的思路...