Poj 1904 King's Quest 强连通分量
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Poj 1904 King's Quest 强连通分量相关的知识,希望对你有一定的参考价值。
题目链接:
http://poj.org/problem?id=1904
题意:
有n个王子和n个公主,王子只能娶自己心仪的公主(一个王子可能会有多个心仪的公主),现已给出一个完美匹配,问每个王子都可以取哪些公主,并且保证取了一个公主后,全局还是存在完美匹配。
题解:
1、建图:
如果王子u对公主v心仪,则连一条边u->v。在样例给出的那组完美匹配中,如果王子u娶了公主v,连一条边v->u。
2、求强连通分量:
如果王子和自己心仪的公主属于同一个强连通分量,那么王子就可以娶这个公主。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<stack> 5 #include<vector> 6 #include<cstring> 7 using namespace std; 8 9 const int maxn=4444; 10 11 int N; 12 13 struct Edge{ 14 int v,ne; 15 Edge(int v,int ne):v(v),ne(ne){} 16 Edge(){} 17 }egs[201010+maxn]; 18 19 int head[maxn],tot; 20 21 void addEdge(int u,int v){ 22 egs[tot]=Edge(v,head[u]); 23 head[u]=tot++; 24 } 25 26 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; 27 stack<int> S; 28 //读入写出优化 29 int scan(){ 30 int ret=0,flag=0; char ch; 31 if((ch=getchar())==‘-‘) flag=1; 32 else if(ch>=‘0‘&&ch<=‘9‘) ret=ch-‘0‘; 33 while((ch=getchar())>=‘0‘&&ch<=‘9‘) ret=ret*10+ch-‘0‘; 34 return flag?-ret:ret; 35 } 36 37 void out(int x){ 38 if(x>9) out(x/10); 39 putchar(x%10+‘0‘); 40 } 41 //强连通 42 void dfs(int u){ 43 pre[u]=lowlink[u]=++dfs_clock; 44 S.push(u); 45 for(int i=head[u];i!=-1;i=egs[i].ne){ 46 Edge& e=egs[i]; 47 int v=e.v; 48 if(!pre[v]){ 49 dfs(v); 50 lowlink[u]=min(lowlink[u],lowlink[v]); 51 }else if(!sccno[v]){ 52 lowlink[u]=min(lowlink[u],pre[v]); 53 } 54 } 55 if(lowlink[u]==pre[u]){ 56 scc_cnt++; 57 for(;;){ 58 int x=S.top(); S.pop(); 59 sccno[x]=scc_cnt; 60 if(x==u) break; 61 } 62 } 63 } 64 65 void find_scc(int n){ 66 dfs_clock=scc_cnt=0; 67 memset(sccno,0,sizeof(sccno)); 68 memset(pre,0,sizeof(pre)); 69 for(int i=0;i<n;i++){ 70 if(!pre[i]) dfs(i); 71 } 72 } 73 //建图 74 void build(){ 75 int cnt,v; 76 for(int i=0;i<N;i++){ 77 cnt=scan(); 78 while(cnt--){ 79 v=scan(); v--; 80 addEdge(i,v+N); 81 } 82 } 83 for(int i=0;i<N;i++){ 84 v=scan(); v--; 85 addEdge(v+N,i); 86 } 87 } 88 89 void init(){ 90 memset(head,-1,sizeof(head)); 91 tot=0; 92 } 93 94 int ans[201010],t; 95 96 int main(){ 97 while(scanf("%d",&N)==1&&N){ 98 init(); 99 build(); 100 find_scc(2*N); 101 for(int i=0;i<N;i++){ 102 t=0; 103 for(int j=head[i];j!=-1;j=egs[j].ne){ 104 Edge& e=egs[j]; 105 int v=e.v; 106 if(sccno[i]==sccno[v]) ans[t++]=v; 107 } 108 sort(ans,ans+t); 109 out(t); 110 for(int i=0;i<t;i++){ 111 putchar(‘ ‘); 112 out(ans[i]+1-N); 113 } 114 putchar(‘\n‘); 115 } 116 } 117 return 0; 118 }
以上是关于Poj 1904 King's Quest 强连通分量的主要内容,如果未能解决你的问题,请参考以下文章
POJ 1904 King's Quest 强连通分量+二分图增广判定
King's Quest POJ - 1904(强连通分量)
POJ3682 King Arthur's Birthday Celebration