Marriage Match IITime
limit:2000/1000 MS (java/others) Memory limit:32768/32768 K (java/others)
Total submission (s): 2307 Accepted Submission (s): 792
Problem descriptionpresumably, you have known the question of stable marriage match. A girl would choose a boy; It is similar as the game of playing House we used to play when we are kids. What is a happy time as so many friends playing together. And it is normal, a fight or a quarrel breaks out, but we'll still play together after that, because we are kids.
Now, there is 2n kids, n boys numbered from 1 to N, and n girls numbered from 1 to N. You know, ladies first. So, every girl can choose a boy first, with whom she had not quarreled, to make up a family. Besides, the girl X can also choose Boy Z to is her boyfriend when she friend, girl Y have not quarreled with him. Furthermore, the friendship is mutual, which means a and C were friends provided that A and B were friends and B and C are f Riend.
Once every girl finds their boyfriends they would start a new round of this game-marriage match. At the end of each round, every girl would start to find a new boyfriend, who she had not chosen before. So the game goes on.
Now, here's the question for you, how many rounds can these 2n kids totally play this game?
Inputthere is several test cases. First is a integer T, means the number of test cases.
Each test case is starts with three integer n, M and F in a line (3<=n<=100,0<m<n*n,0<=f<n). n means there is 2*n children, n Girls (number from 1 to n) and N Boys (number from 1 to n).
Then M lines follow. Each line contains the numbers a and B, means girl A and boy B had never quarreled with each other.
Then f lines follow. Each line contains the numbers C and D, means girl C and girl D are good friends.
Outputfor each case, output a number on one line. The maximal number of marriage Match the children can play.
Sample Input
14 5 21 12 33 24 24 41 42 3
Sample Output
2
This problem at the beginning I use Hungarian + cut, and then do the network stream when you see a great God blog on a piece of analysis deep experience, and use the maximum flow to do it again.
Links: http://blog.csdn.net/qq564690377/article/details/7857983
Here I will only analyze the two points match, in fact, is very simple, is based on and check set will be connected to the relationship all together, and then have Hungary run again,
After each run, delete the current node (girl) from its current matching node (boy) and continue running Hungary until the largest
The number of runs is the maximum number of rounds, so the number of matches is small and N.
Now the code:
Network flow:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <queue>
#define Min (b) a<b?a:b
#define INF 1000000000
#define MAXN 20000
#define MAXH 400
using namespace Std;
typedef struct//forward star Save map
{
int to,next,w;
}node;
typedef struct
{
int x,t;
}DEP;
Node E[MAXN];
int head[maxh],headx[maxh],deep[maxh],cnt;
int SET[MAXH],MAP[MAXH][MAXH];
int n,m,f;
wangluoliu//////////////////////////////
void Init ()
{
memset (head,-1,sizeof (head));
cnt=0;
}
void Add (int a,int b,int c)
{
E[cnt].to=b;
E[cnt].w=c;
E[cnt].next=head[a];
head[a]=cnt++;
E[cnt].to=a;
e[cnt].w=0;
E[CNT].NEXT=HEAD[B];
head[b]=cnt++;
}
int min (int x,int y)
{
Return x<y?x:y;
}
int BFS (int s,int t,int N)
{
memset (deep,255,sizeof (deep));
queue<dep>q;
DEP Fir,nex;
Fir.x=s;
fir.t=0;
deep[s]=0;
Q.push (FIR);
while (! Q.empty ())
{
Fir=q.front ();
Q.pop ();
for (int i=head[fir.x];i+1;i=e[i].next)
{
nex.x=e[i].to;
nex.t=fir.t+1;
if (deep[nex.x]!=-1| |! E[I].W)
Continue
deep[nex.x]=nex.t;
Q.push (NEX);
}
}
for (int i=0;i<=n;i++)
Headx[i]=head[i];
return deep[t]!=-1;
}
int dfs (int s,int t,int flow)
{
if (s==t)
return flow;
int newflow=0;
for (int i=headx[s];i+1;i=e[i].next)
{
Headx[s]=i;
int to=e[i].to;
int W=E[I].W;
if (!w| | DEEP[TO]!=DEEP[S]+1)
Continue
int Temp=dfs (To,t,min (W,flow-newflow));
Newflow+=temp;
E[i].w-=temp;
E[i^1].w+=temp;
if (Newflow==flow)
Break
}
if (!newflow) deep[s]=0;
return newflow;
}
int dinic (int s,int t,int m)
{
int sum=0;
while (BFS (s,t,m))
{
Sum+=dfs (S,t,inf);
}
return sum;
}
bingchaji///////////////////////////////////
int findx (int x)
{
if (set[x]!=x)
Set[x]=findx (Set[x]);
return set[x];
}
void Fun (int x,int y)
{
X=FINDX (x);
Y=findx (y);
if (x!=y)
Set[x]=y;
}
jiantu////////////////////////////
void built (int mid)
{
Init ();//forward star initialization
int s=2*n+1,t=2*n+2;
for (int i=1;i<=n;i++)
{
Add (S,i,mid);
Add (I+n,t,mid);
for (int j=1;j<=n;j++)
{
if (Map[i][j])
{
Add (i,j+n,1);
}
}
}
}
////////////////////////////////////////////////////////////////////////
int main ()
{
int T;
int A, B;
int l,r,mid;
scanf ("%d", &t);
while (t--)
{
scanf ("%d%d%d", &n,&m,&f);
for (int i=0;i<=n;i++)//initialization
{
Set[i]=i;
for (int j=0;j<=n;j++)
map[i][j]=0;
}
for (int i=0;i<m;i++)
{
scanf ("%d%d", &a,&b);
Map[a][b]=1;
}
for (int i=0;i<f;i++)
{
scanf ("%d%d", &a,&b);
Fun (A, b);
}
for (int i=1;i<=n;i++)
{
int xi=findx (i);
for (int j=1;j<=n;j++)
{
int Yi=findx (j);
if (XI==YI&&I!=J)
{
for (int k=1;k<=n;k++)
{
if (Map[j][k])
{
Map[i][k]=1;
}
}
}
}
}
l=0,r=n+1;
while (L!=R-1)
{
printf ("xcwdf\n");
Mid= (L+R)/2;
Built (mid);
if (Dinic (2*n+1,2*n+2,2*n+2) ==n*mid)
{
L=mid;
}
Else
{
R=mid;
}
}
printf ("%d\n", L);
}
return 0;
}
Two-point matching:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#define MAXN 200
using namespace Std;
int MARKD[MAXN],MARKX[MAXN],XM[MAXN][MAXN];
int SET[MAXN];
int n,m,f;
int findx (int x)
{
if (X!=set[x])
Set[x]=findx (Set[x]);
return set[x];
}
void Fun (int x,int y)
{
X=FINDX (x);
Y=findx (y);
if (x!=y)
{
Set[y]=x;
}
}
int xyl (int x)
{
for (int i=1;i<=n;i++)
{
if (Xm[x][i]&&!markd[i])
{
Markd[i]=1;
if (markx[i]==-1| | Xyl (Markx[i]))
{
Markx[i]=x;
return 1;
}
}
}
return 0;
}
int main ()
{
int T;
int A, B;
scanf ("%d", &t);
while (t--)
{
scanf ("%d%d%d", &n,&m,&f);
memset (Xm,0,sizeof (XM));
for (int i=1;i<=n;i++)
Set[i]=i;
for (int i=1;i<=m;i++)
{
scanf ("%d%d", &a,&b);
Xm[a][b]=1;
}
for (int i=1;i<=f;i++)
{
scanf ("%d%d", &a,&b);
Fun (A, b);
}
for (int i=1;i<=n;i++)
{
int xi=findx (i);
for (int j=1;j<=n;j++)
{
int Yi=findx (j);
if (XI==YI&&I!=J)
{
for (int k=1;k<=n;k++)
{
if (Xm[j][k])
Xm[i][k]=1;
}
}
}
}
int cnt=0;
while (1)
{
memset (markx,255,sizeof (MARKX));
int sum=0;
for (int i=1;i<=n;i++)
{
memset (markd,0,sizeof (MARKD));
Sum+=xyl (i);
}
if (sum<n)
Break
cnt++;
for (int i=1;i<=n;i++)
{
xm[markx[i]][i]=0; Erase the current matching edge
}
}
printf ("%d\n", CNT);
}
return 0;
}
HDU 3081 "binary match + check set + Delete Edge | | Max path + Check set + Binary enumeration "