1. 程式人生 > >King's Quest POJ - 1904(強連通分量)

King's Quest POJ - 1904(強連通分量)

cstring cloc opened name 屬於 tor con return string

建圖:王子u喜歡女孩v,則u到v連一條邊。對於給出的初始完美匹配,王子u與女孩v匹配,則v到u連一條邊。然後求SCC。

顯然對於同一個SCC中王子數目和女孩數目是相等的,並且從某個王子出發能夠到達所有女孩,這樣,王子可以和屬於同一個SCC中的任意一個女孩結婚,而不會影響其他王子。

技術分享圖片
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include 
<stack> #include <vector> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 500100, INF = 0x7fffffff; int pre[maxn], low[maxn], sccno[maxn], dfs_clock, scc_cnt, cnt; int head[maxn]; vector<int> G[maxn]; stack<int> S; int n, k; struct node { int u, v, next; }Node[maxn];
void add(int u, int v) { Node[cnt].u = u; Node[cnt].v = v; Node[cnt].next = head[u]; head[u] = cnt++; } void dfs(int u) { pre[u] = low[u] = ++dfs_clock; S.push(u); for(int i=head[u]; i!=-1; i=Node[i].next) { int v = Node[i].v; if(!pre[v]) { dfs(v); low[u]
= min(low[u], low[v]); } else if(!sccno[v]) low[u] = min(low[u], pre[v]); } if(low[u] == pre[u]) { scc_cnt++; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if(x == u) break; } } } void init() { cnt = 0; mem(head, -1); mem(pre, 0); mem(low, 0); mem(sccno, 0); } int main() { init(); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&k); for(int j=0; j<k; j++) { int v; scanf("%d",&v); add(i, n+v); } } for(int i=1; i<=n; i++) { int v; scanf("%d",&v); add(n+v, i); } for(int i=1; i<=n; i++) if(!pre[i]) dfs(i); // cout<< 1211 <<endl; for(int i=1; i<=n; i++) { for(int j=head[i]; j!=-1; j=Node[j].next) { if(sccno[i] == sccno[Node[j].v]) { G[i].push_back(Node[j].v); } } } for(int i=1; i<=n; i++) sort(G[i].begin(), G[i].end()); for(int i=1; i<=n; i++) { printf("%d ",G[i].size()); for(int j=0; j<G[i].size(); j++) printf("%d%s",G[i][j] - n,(j==G[i].size()-1)?"\n":" "); } return 0; }
View Code

King's Quest POJ - 1904(強連通分量)