题意略。
思路:
我们按大臣给出的完美匹配,将王子向少女和少女向王子连一条双向边,这样,这张图里就出现了n个强连通分量。如果将王子记为x,将少女记为y,则:
如果xi 不再选择 yi,而是选择了 yj ,为了保持匹配不变,xj需要选择yi,或者 xj 选择了 yk ,最终 xk 选择了 yi。不论如何,这都是一个环,此时你会发现
多个小连通分量合成了一个大联通分量,也就是说,当前王子只要选择自己连通分量之内喜欢的姑娘,通过两点之间互达的性质,我们总能给他的原配找
到别的王子。
本题输入可能有点大,使用输入输出外挂比较合适。
详见代码:
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> using namespace std; const int maxn = 4005; int V,n; vector<int> graph[maxn]; vector<int> rgraph[maxn]; vector<int> store[maxn]; vector<int> vs; bool used[maxn]; int component[maxn]; int scan(){ int res = 0,ch,flag = 0; if((ch = getchar()) == '-') flag = 1; else if(ch >= '0' && ch <= '9') res = ch - '0'; while((ch = getchar()) >= '0' && ch <= '9') res = res * 10 + ch - '0'; return flag ? -res : res; } void out(int a){ if(a > 9) out(a / 10); putchar(a % 10 + '0'); } void add_e(int from,int to){ graph[from].push_back(to); rgraph[to].push_back(from); } void dfs(int v){ used[v] = true; for(int i = 0;i < graph[v].size();++i){ int to = graph[v][i]; if(used[to]) continue; dfs(to); } vs.push_back(v); } void rdfs(int v,int k){ used[v] = true; component[v] = k; for(int i = 0;i < rgraph[v].size();++i){ int to = rgraph[v][i]; if(used[to]) continue; rdfs(to,k); } } int scc(){ memset(used,false,sizeof(used)); vs.clear(); for(int v = 1;v <= V;++v){ if(used[v]) continue; dfs(v); } memset(used,false,sizeof(used)); int k = 0; for(int i = vs.size() - 1;i >= 0;--i){ if(!used[vs[i]]) rdfs(vs[i],k++); } return k; } int main(){ n = scan(); for(int i = 0;i < maxn;++i){ graph[i].clear(); rgraph[i].clear(); store[i].clear(); } memset(component,0,sizeof(component)); for(int i = 1;i <= n;++i){ int ki = scan(); int v; for(int j = 0;j < ki;++j){ v = scan(); v += n; add_e(i,v); } } int girl; for(int i = 1;i <= n;++i){ girl = scan(); girl += n; add_e(girl,i); } V = n<<1; int numb = scc(); for(int i = 1;i <= n;++i){ int part1 = component[i]; for(int j = 0;j < graph[i].size();++j){ int to = graph[i][j]; int part2 = component[to]; if(part2 == part1) store[i].push_back(to - n); } sort(store[i].begin(),store[i].end()); } for(int i = 1;i <= n;++i){ out(store[i].size()); for(int j = 0;j < store[i].size();++j){ putchar(' '); out(store[i][j]); } putchar(' '); } return 0; }