给你n个王子和m个公主,每个王子可以和自己喜欢的公主结婚,问你在不影响最大匹配的前提下每个王子都可以去哪些公主.
思路:
所有王子向他喜欢的公主连一条边,然后匹配一遍,之后再每个匹配的公主连一条指向娶她的王子一条边,然后对于那些光棍王子和单身公主们,其实他们可以和任意他们喜欢的人匹配,因为可以让自己幸福,然后拆散一对别人已经匹配好的,虽然不道德,但是仍然满足总的最大匹配数不变,所以对于每一个光棍男我们就给他虚拟出一个女朋友,所有人都喜欢这个女的,但是这个女的只喜欢并且和该光棍男匹配,女的也类似这样弄,最后每个人都有匹配的对象了,此时我们只要跑一遍强连通,同一个强连通分量里的男和女可以随意匹配..
#include<stdio.h> #include<string.h> #include<algorithm> #include<stack> #include<map> #define N_node 5000 #define N_edge 600000 using namespace std; typedef struct { int to ,next; }STAR; STAR E[N_edge] ,_E[N_edge] ,__E[N_edge]; map<int ,map<int ,int> >mk_map; int list[N_node] ,_list[N_node] ,tot , _tot; int Belong[N_node] ,cout; int mk_dfs[N_node] ,mk_gx[N_node]; int mk_M[550] ,mk_G[550]; stack<int>st; void add(int a, int b) { E[++tot].to = b; E[tot].next = list[a]; list[a] = tot; _E[++_tot].to = a; _E[_tot].next = _list[b]; _list[b] = _tot; } int DFS_XYL(int s) { for(int k = list[s] ;k ;k = E[k].next) { int to = E[k].to; if(mk_dfs[to]) continue; mk_dfs[to] = 1; if(mk_gx[to] == -1 || DFS_XYL(mk_gx[to])) { mk_gx[to] = s; return 1; } } return 0; } void DFS_1(int s) { mk_dfs[s] = 1; for(int k = list[s] ;k ;k = E[k].next) { int to = E[k].to; if(mk_dfs[to]) continue; DFS_1(to); } st.push(s); } void DFS_2(int s) { mk_dfs[s] = 1; Belong[s] = cout; for(int k = _list[s] ;k ;k = _E[k].next) { int to = _E[k].to; if(mk_dfs[to]) continue; DFS_2(to); } } void solve(int cas) { int n ,m ,i ,j; int a ,b ,c; scanf("%d %d" ,&n ,&m); memset(list ,0 ,sizeof(list)); memset(_list ,0 ,sizeof(_list)); tot = _tot = 1; mk_map.clear(); for(i = 1 ;i <= n ;i ++) { scanf("%d" ,&c); while(c--) { scanf("%d" ,&a); add(i ,a + n); mk_map[i][a] = 1; } } memset(mk_gx ,255 ,sizeof(mk_gx)); int sum = 0; for(i = 1 ;i <= n ;i ++) { memset(mk_dfs ,0 ,sizeof(mk_dfs)); mk_M[i] = DFS_XYL(i); sum += mk_M[i]; } for(i = 1 ;i <= m ;i ++) { if(mk_gx[i + n] == -1) mk_G[i] = 0; else { mk_G[i] = 1; add(i + n ,mk_gx[i + n]); } } int nowid = n + m; for(i = 1 ;i <= n ;i ++) { if(mk_M[i]) continue; nowid ++; for(j = 1 ;j <= n ;j ++) add(j ,nowid); add(nowid ,i); } for(i = 1 ;i <= m ;i ++) { if(mk_G[i]) continue; nowid ++; for(j = 1 ;j <= m ;j ++) add(nowid ,j + n); add(i + n ,nowid); } memset(mk_dfs ,0 ,sizeof(mk_dfs)); while(!st.empty()) st.pop(); for(i = 1 ;i <= nowid ;i ++) { if(mk_dfs[i]) continue; DFS_1(i); } cout = 0; memset(mk_dfs ,0 ,sizeof(mk_dfs)); while(!st.empty()) { int to = st.top(); st.pop(); if(mk_dfs[to]) continue; cout ++; DFS_2(to); } printf("Case #%d: " ,cas); int tmp[550]; for(i = 1 ;i <= n ;i ++) { int tt = 0; for(int k = list[i] ;k ;k = E[k].next) { int to = E[k].to; if(mk_map[i][to - n] && Belong[i] == Belong[to]) tmp[++tt] = to - n; } sort(tmp + 1 ,tmp + tt + 1); printf("%d" ,tt); for(int k = 1 ;k <= tt ;k ++) printf(" %d" ,tmp[k]); printf(" "); } } int main () { int cas = 1 ,t; scanf("%d" ,&t); while(t--) { solve(cas++); } return 0; }