HDU4685 Prince and Princess perfect match + strong connectivity, hdu4685princess
Now there are n princes and m princesses. Now I want to associate them. The prince will marry a person he prefers, and the princess cannot make a choice.
This is a tough question. There is a similar question, poj1904. The question is also paired with the prince and the princess, but it is the prince and the princess each has n, and given a perfect match, then, ask each prince to make a choice without affecting the maximum number of matches. The question is to first build the edges that like the relationship, and then connect the edges of the selected princess to the matching prince, after a strong connection, if a prince and a princess are in a strongly connected component, then when they combine, their other half can also find another match in the strong connection, is the result of the question.
This is an upgraded version. What we need to do is first use the Hungary algorithm to find the maximum matching res, and then create a virtual Prince m-res and a single Princess m-res to prepare for matching, create n-res virtual princesses to match with n-res single princes. The process is that virtual princes like every princess, and virtual Princesses will also be liked by every prince, in this way, the maximum match must be n + m-res. find such a perfect match, and then apply the idea of poj1904 to do it with strong connectivity. We recommend that you do the following first.
Code:
#include<iostream>#include<cstdio>#include<string>#include<cmath>#include<queue>#include<stack>#include<map>#include<cstring>#include<algorithm>#define rep(i,a,b) for(int i=(a);i<(b);i++)#define rev(i,a,b) for(int i=(a);i>=(b);i--)#define clr(a,x) memset(a,x,sizeof a)#define inf 0x3f3f3f3ftypedef long long LL;using namespace std;const int eps=0.00000001;const int maxn=2005;const int maxm=maxn*maxn/2;int first[maxn],link[maxn];int nex[maxm],w[maxm],v[maxm],u[maxm];bool done[maxn],g[maxn][maxn];int n,m,ecnt;void add_(int a,int b,int c=0){ u[ecnt]=a; v[ecnt]=b; w[ecnt]=c; nex[ecnt]=first[a]; first[a]=ecnt++;}bool dfs(int s){ for(int e=first[s];~e;e=nex[e]) if(!done[v[e]]) { done[v[e]]=true; if(link[v[e]]==-1||dfs(link[v[e]])) { link[v[e]]=s; return true; } } return 0;}int hungary(int n){ int ans=0; clr(link,-1); for(int i=1;i<=n;i++) { clr(done,false); if(dfs(i))ans++; } return ans;}int low[maxn],dfn[maxn],stck[maxn],belong[maxn];int index,top,scc;bool ins[maxn];int num[maxn];int in[maxn],out[maxn];void tarjan(int u){ low[u]=dfn[u]=++index; stck[top++]=u; ins[u]=1; for(int e=first[u];~e;e=nex[e]) { if(!dfn[v[e]]) { tarjan(v[e]); low[u]=min(low[u],low[v[e]]); } else if(ins[v[e]])low[u]=min(low[u],dfn[v[e]]); } if(low[u]==dfn[u]) { int v; scc++; do { v=stck[--top]; ins[v]=false; belong[v]=scc; num[scc]++; }while(v!=u); }}void solve(int n){ clr(dfn,0); clr(ins,0); clr(num,0); index=scc=top=0; for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i);}int main(){ int t,a,b,c,k,cas=1,key=1000; scanf("%d",&t); while(t--) { clr(first,-1);ecnt=0; clr(g,false); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&k); while(k--) { scanf("%d",&a); if(!g[i][a]) { g[i][a]=1; add_(i,a+key); } } } int res=hungary(n); int nn=n+m-res; for(int i=n+1;i<=nn;i++) for(int j=1;j<=nn;j++) add_(i,j+key),g[i][j]=1; for(int i=1;i<=n;i++) for(int j=m+1;j<=nn;j++) add_(i,j+key),g[i][j]=1; hungary(nn); ecnt=0;clr(first,-1); for(int i=1;i<=nn;i++) if(link[i+key]!=-1)add_(i+nn,link[i+key]); for(int i=1;i<=nn;i++) for(int j=1;j<=nn;j++) if(g[i][j])add_(i,j+nn); solve(2*nn); printf("Case #%d:\n",cas++); int ans[1000]; for(int i=1;i<=n;i++) { int en=0; for(int j=1;j<=m;j++) if(g[i][j]&&belong[j+nn]==belong[i])ans[en++]=j; printf("%d",en); for(int i=0;i<en;i++) printf(" %d",ans[i]); puts(""); } } return 0;}