很好的题解:http://www.cnblogs.com/zxndgv/archive/2011/08/06/2129333.html
题意:一个国王有n个王子,同时有n个女孩。每个王子都有自己喜欢的若干个女孩,现给定一个合法的完备匹配(也就是一个王子娶其中一个自己喜欢女孩),求每个王子可以选择哪些女孩可以让剩下的每个王子依旧能够选择到自己喜欢的一个女孩。
分析:草..居然是强连通图...主要事先给了一个完美匹配了,故可以用强连通图,在强连通图内王子可以娶自己喜欢的女孩...(尼玛变态,,,,给个匹配就变成别的算法了.)
详解看上面的链接..
// File Name: 1904.cpp // Author: Zlbing // Created Time: 2013/4/12 14:27:16 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=2005<<1; vector<int> G[MAXN]; int lowlink[MAXN],sccno[MAXN],pre[MAXN]; int scc_cnt,dfs_clock; stack<int> S; int n; void dfs(int u) { pre[u]=lowlink[u]=++dfs_clock; S.push(u); for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!pre[v]) { dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); }else if(!sccno[v]) { lowlink[u]=min(lowlink[u],pre[v]); } } if(lowlink[u]==pre[u]) { scc_cnt++; for(;;){ int t=S.top();S.pop(); sccno[t]=scc_cnt; if(t==u)break; } } } void find_scc(){ memset(sccno,0,sizeof(sccno)); memset(lowlink,0,sizeof(lowlink)); memset(pre,0,sizeof(pre)); dfs_clock=0,scc_cnt=0; for(int i=1;i<=n;i++) if(!pre[i])dfs(i); } int main() { while(~scanf("%d",&n)) { REP(i,1,n)G[i].clear(); REP(i,1,n) { int a,b; scanf("%d",&a); REP(j,1,a) { scanf("%d",&b); G[i].push_back(b+n); } } REP(i,1,n) { int a; scanf("%d",&a); G[a+n].push_back(i); } find_scc(); REP(i,1,n) { int k=sccno[i]; vector<int> A; REP(j,1,G[i].size()) { int u=G[i][j-1]; if(sccno[u]==k) A.push_back(u-n); } sort(A.begin(),A.end()); printf("%d",A.size()); REP(i,1,A.size()) { printf(" %d",A[i-1]); } printf("\n"); } } return 0; }