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 强连通分量

时间: 2024-08-05 19:09:59

Poj 1904 King's Quest 强连通分量的相关文章

POJ - 1904 King&#39;s Quest(强连通分量+二分图匹配)

题目大意:有N个帅哥和N个美女,现在给出每个帅哥所喜欢的美女的编号,和一个帅哥和美女的完美匹配 问每个帅哥可以娶多少个美女,且当他娶完这个美女后,剩下的人还可以完美匹配 解题思路:神题啊,给一个大神的详细解答 具体是这样的,首先先建边,把帅哥和能娶到的美女连边,再把完美匹配的美女和帅哥连边,这样就形成了一张有向图了 接着,找出这张有向图的所有强连通分量,在强连通分量里面的帅哥都可以娶到自己喜欢的美女,且娶完这个美女后,不会影响到其他人 为什么呢? 假设xi为帅哥,yi和yj为美女,假设给定的完美

POJ 1904 King&#39;s Quest 强连通分量+二分图增广判定

http://www.cnblogs.com/zxndgv/archive/2011/08/06/2129333.html 这位神说的很好 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <string> #include <stack> #include <ve

POJ 1904 King&#39;s Quest强连通分量+二分图完美匹配

题目描述: Description Once upon a time there lived a king and he had N sons. And there were N beautiful girls in the kingdom and the king knew about each of his sons which of those girls he did like. The sons of the king were young and light-headed, so i

POJ 1904 King&#39;s Quest(强连通)

POJ 1904 King's Quest 题目链接 题意:n个男人,每个人都有一个喜欢的女人列表,现在给一个完美匹配,问所有完美匹配中,每个人可能娶到的女人列表 思路:强连通,建图,男的连一条边指向女,然后完美匹配的边女的指向男,然后求强连通,在同一个强连通分支并且是自己想娶的的就可能娶到 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #inc

poj 1904 King&#39;s Quest

King's Quest 题意:有N个王子和N个妹子;(1 <= N <= 2000)第i个王子喜欢Ki个妹子:(详见sample)题给一个完美匹配,即每一个王子和喜欢的一个妹子结婚:问每一个王子可以有几种选择(在自己喜欢的妹子里面选),并输出可选的妹子的标号(升序): Sample Input 4 (N) 2 1 2 (Ki) 2 1 2 2 2 3 2 3 4 1 2 3 4 (完美匹配) Sample Output 2 1 2 2 1 2 1 3 1 4 分析:图匹配问题,1~N为王子的

POJ 2186 Popular Cows (强连通分量)

POJ 2186 Popular Cows 链接:http://poj.org/problem?id=2186 题意:每头奶牛都梦想着成为牧群中最受奶牛仰慕的奶牛.在牧群中,有N 头奶牛,1≤N≤10,000,给定M 对(1≤M≤50,000)有序对(A, B),表示A 仰慕B.由于仰慕关系具有传递性,也就是说,如果A 仰慕B,B 仰慕C,则A 也仰慕C,即使在给定的M 对关系中并没有(A, C).你的任务是计算牧群中受每头奶牛仰慕的奶牛数量. 思路:首先可以知道,在同一个强连通分量内的点一定互

poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27496   Accepted: 11059 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows

POJ 2375 Cow Ski Area (强连通分量)

题目地址:POJ 2375 对每一个点向与之相邻并h小于该点的点加有向边. 然后强连通缩点.问题就转化成了最少加几条边使得图为强连通图,取入度为0和出度为0的点数的较大者就可以.注意,当强连通分量仅仅有一个的时候.答案是0,而不是1. 代码例如以下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #in

HDU - 3861 The King’s Problem(强连通分量+最小路径覆盖)

题目大意:给出一张有向图,要求你将这些点进行划分,划分依据如下 1.如果两个点互相可达,那么这两个点必须在一个集合中 2.同一个集合中任意两个点u,v要满足,要么u能到达v,要么v能到达u 3.一个点只能被划分到一个集合 问最少能划分成几个点集 解题思路:首先先求出所有的强连通分量,满足条件1 满足条件2,3的话,就要求出最小路径覆盖 所以可以将所有的强连通分量进行缩点,桥作为连接,然后匈牙利一下,求出最大匹配数,再用强连通分量的数量-最大匹配数,就是答案了 #include <cstdio>