poj 1904 King's Quest 强连通
朴素的想法,对于每个王子,选取一个他喜欢的公主,然后对其他的进行一遍匹配看是否完备,不过时间复杂度太高,仔细想想这一过程,先看题目中给出的初始配对,王子甲本身配对的是公主甲,如果甲还可以选其他的公主比如说公主乙,那么如果王子乙可以选公主甲,那么结束,如果不能,则重复刚才的做法(其实就是匹配寻找增广路的过程),直到找到公主甲为止,这时发现,刚才走的其实是个环,所以说某王子可选的公主都跟他在一个强连通分量里。
#include<cstdio> #include<algorithm> #include<vector> #include<cstring> #include<stack> using namespace std; const int maxn = 12000 + 10; vector<int> G[maxn], G2[maxn]; vector<int> S; vector<int> ans[maxn]; int vis[maxn], sccno[maxn], scc_cnt; int n; int max(int a,int b) { if(a>b) return a; else return b; } void dfs1(int u) { if(vis[u]) return; vis[u] = 1; for(int i = 0; i < G[u].size(); i++) dfs1(G[u][i]); S.push_back(u); } void dfs2(int u) { if(sccno[u]) return; sccno[u] = scc_cnt; for(int i = 0; i < G2[u].size(); i++) dfs2(G2[u][i]); } void find_scc(int n) { int i; scc_cnt = 0; S.clear(); memset(sccno, 0, sizeof(sccno)); memset(vis, 0, sizeof(vis)); for(i = 0; i < n; i++) dfs1(i); for(i = n-1; i >= 0; i--) if(!sccno[S[i]]) { scc_cnt++; dfs2(S[i]); } } int main() { int i,j,k; int gir; while(scanf("%d",&n)!=EOF) { for(i=0;i<=2*n;i++) { G[i].clear(); G2[i].clear(); ans[i].clear(); } for(i=1;i<=n;i++) { scanf("%d",&k); for(j=1;j<=k;j++) { scanf("%d",&gir); G[i-1].push_back(gir+n-1); G2[gir+n-1].push_back(i-1); } } for(i=1;i<=n;i++) { scanf("%d",&k); G[k-1+n].push_back(i-1); G2[i-1].push_back(k-1+n); } n=n*2; find_scc(n); n/=2; for(i=0;i<n;i++) for(j=0;j<G[i].size();j++) if(sccno[i]==sccno[G[i][j]]) ans[i].push_back(G[i][j]); for(i=0;i<n;i++) sort(ans[i].begin(),ans[i].end()); for(i=0;i<n;i++) { printf("%d",ans[i].size()); for(j=0;j<ans[i].size();j++) printf(" %d",ans[i][j]+1-n); printf("\n"); } } return 0; }