Poj 1904 King's Quest 强连通分量

Posted

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

POJ3682King Arthur's Birthday Celebration(数学期望||概率DP)

poj1904 完美匹配+Tarjan

POJ1904(有向图缩点+输入输出挂参考)