POJ 1904 King's Quest(强连通分量)

 

题目大意

 

一个国王,有 n(1<=n<=2000) 个儿子,在这个国家中有 n 个漂亮的妹子。每个儿子都有自己喜欢的妹子(可以是多个)。每个妹子只能嫁一个人,每个儿子只娶自己喜欢的人

国王的巫师调查到了每个儿子喜欢哪些妹子,并且为每一个儿子分配了他喜欢的妹子让他娶

但是国王不满意,说是要巫师统计出每个儿子能够娶哪些人,使得儿子们娶了这个妹子后,其他的每个儿子都有妹子可以娶

题目给出了每个儿子喜欢的人,以及巫师做好的一个”妹子分配“方案

 

好绕的题意~

 

做法分析

 

对于每个王子 A,假设他喜欢妹子 B,建边 <A, B>

对于每个婚姻分配,比如王子 A 娶妹子 B,建边 <B, A>

对建好的图缩点,处于同一个强连通分量重的王子和妹子可以混搭(前提是这个王子喜欢这个妹子)

这道题挺神的,不知道为什么 AC 的人这么多,算了,POJ 上面题目的通过量向来很奇葩。。。

 

参考代码

 

POJ 1904
  1 #include <vector>
  2 #include <stack>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 
  8 using namespace std;
  9 
 10 const int N=4006;
 11 
 12 vector <int> arc[N], scc[N], ans[N];
 13 int n, T, ind;
 14 int dfn[N], low[N], id[N];
 15 stack <int> s;
 16 bool vs[N], love[N][N];
 17 
 18 void tarjan(int u)
 19 {
 20     s.push(u), vs[u]=1;
 21     dfn[u]=low[u]=T++;
 22     int len=(int)arc[u].size();
 23     for(int i=0; i<len; i++)
 24     {
 25         int v=arc[u][i];
 26         if(dfn[v]==-1)
 27         {
 28             tarjan(v);
 29             if(low[u]>low[v]) low[u]=low[v];
 30         }
 31         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
 32     }
 33     if(low[u]==dfn[u])
 34     {
 35         for(int v; 1; )
 36         {
 37             v=s.top();
 38             s.pop(), vs[v]=0;
 39             scc[ind].push_back(v), id[v]=ind;
 40             if(v==u) break;
 41         }
 42         ind++;
 43     }
 44 }
 45 
 46 int main()
 47 {
 48     scanf("%d", &n);
 49     for(int i=1; i<=n; i++)
 50         for(int j=1; j<=n; j++)
 51             love[i][j]=0;
 52     for(int i=1, len, u; i<=n; i++)
 53     {
 54         scanf("%d", &len);
 55         arc[i].clear();
 56         for(int j=0; j<len; j++)
 57         {
 58             scanf("%d", &u);
 59             arc[i].push_back(n+u);
 60             love[i][u]=1;
 61         }
 62     }
 63     for(int i=1, u; i<=n; i++)
 64     {
 65         scanf("%d", &u);
 66         arc[u+n].push_back(i);
 67     }
 68     for(int i=1; i<=n+n; i++) vs[i]=0, dfn[i]=-1, scc[i].clear();
 69     while(!s.empty()) s.pop();
 70     ind=T=0;
 71     for(int i=1; i<=n+n; i++) if(dfn[i]==-1) tarjan(i);
 72     for(int i=0; i<ind; i++) sort(scc[i].begin(), scc[i].end());
 73     for(int i=1; i<=n; i++) ans[i].clear();
 74     for(int i=1; i<=n; i++)
 75     {
 76         int u=id[i];
 77         int L=0, R=(int)scc[u].size()-1;
 78         int len=R+1;
 79         while(L<R)
 80         {
 81             int mid=(L+R)>>1;
 82             if(scc[u][mid]<=n) L=mid+1;
 83             else R=mid;
 84         }
 85         if(scc[u][L]<=n) L++;
 86         for(int j=L; j<len; j++)
 87         {
 88             if(!love[i][scc[u][j]-n]) continue;
 89             ans[i].push_back(scc[u][j]-n);
 90         }
 91     }
 92     for(int i=1; i<=n; i++)
 93     {
 94         int len=(int)ans[i].size();
 95         printf("%d ", len);
 96         for(int j=0; j<len; j++)
 97         {
 98             printf("%d", ans[i][j]);
 99             if(j==len-1) printf("\n"); else printf(" ");
100         }
101     }
102     return 0;
103 }

 

AC通道

 

POJ 1904 King's Quest

 

 

 

posted @ 2013-03-16 18:00  jianzhang.zj  阅读(457)  评论(0编辑  收藏  举报