题目链接:http://poj.org/problem?id=1904
题目大意:列出一张单子,在有一个完美匹配的基础上得到一个匹配表保证任一王子选择了一个钟意女子作为妻子,其他王子还有钟意的女子可以选择.
题目思路:如果把最终结果看成有向图(王子指向其钟意女子,完美匹配中的女子指向其匹配的王子),可以发现王子和其钟意的女子必然处于同一个强连通图里,但是需要注意处于同一个强连通图里的王子和女子,该女子不一定是该王子的钟意对象.
如这个数据:
3
2 1 2
2 1 3
2 2 3
1 3 2
很容易发现,所有王子和所有女子强连通,但是女子3不是王子1的钟意对象.
代码:
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include <math.h> #include <time.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <string> #include <iostream> #include <algorithm> using namespace std; #define ull unsigned __int64 //#define ll __int64 //#define ull unsigned long long #define ll long long #define son1 New(p.xl,xm,p.yl,ym),(rt<<2)-2 #define son2 New(p.xl,xm,min(ym+1,p.yr),p.yr),(rt<<2)-1 #define son3 New(min(xm+1,p.xr),p.xr,p.yl,ym),rt<<2 #define son4 New(min(xm+1,p.xr),p.xr,min(ym+1,p.yr),p.yr),rt<<2|1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define middle (l+r)>>1 #define MOD 1000000007 #define esp (1e-8) const int INF=0x3F3F3F3F; const double DINF=10000.00; //const double pi=acos(-1.0); const int M=4010; int min(int x,int y){return x<y? x:y;} int max(int x,int y){return x>y? x:y;} void swap(int& x,int& y){int t=x;x=y;y=t;} int T,cas; vector<int>init[M<<4],pot[M<<4]; int low[M],pre[M],idx[M],ss[M]; int n,nn,Index,top,N,mtx[M>>1][M>>1]; void dfs(int u){ low[u]=pre[u]=++Index; ss[++top]=u; for(int i=0;i<init[u].size();i++){ int v=init[u][i]; if(pre[v]==-1) dfs(v),low[u]=min(low[u],low[v]); else if(idx[v]==-1) low[u]=min(low[u],pre[v]); } if(low[u]==pre[u]){ int v=-1; pot[++nn].clear(); while(u!=v) pot[idx[v=ss[top--]]=nn].push_back(v); } } void Tarjan(){ memset(idx,-1,sizeof(idx)); memset(pre,-1,sizeof(pre)); Index=top=nn=0,ss[0]=-1; for(int u=1;u<=n;u++) if(pre[u]==-1) dfs(u); } struct cmp{ bool operator () (int a,int b){ return a > b; } }; void _sof(){ Tarjan(); priority_queue<int, vector<int>, cmp>q; for(int u=1;u<=N;u++){ for(int i=0;i<pot[idx[u]].size();i++){ int v=pot[idx[u]][i]; if(v>N && mtx[u][v-N]) q.push(v-N); } printf("%d",q.size()); while(!q.empty()) printf(" %d",q.top()),q.pop(); puts(""); } } void _init(){ memset(mtx,0,sizeof(mtx)),n=N; for(int u=1,k,v;u<=N;u++){ init[u].clear(); scanf("%d",&k); while(k--){ scanf("%d",&v); mtx[u][v]=1; init[u].push_back(v+N); n=max(n,v+N); } } for(int u=1,v;u<=N;u++){ scanf("%d",&v); init[v+N].clear(); init[v+N].push_back(u); } _sof(); } int main(){ //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); //_init() //scanf("%d",&T);for(cas=1;cas<=T;cas++) _init(); while(~scanf("%d",&N)) _init(); return 0; }