建图很好想到,主要是后面判断这条匹配边是不是必须变。 只需要吧当前这个匹配拆开,并且在图中吧这条边去掉。对对于左边的点去找增光路,如果不能找到,说明就是匹配必须边。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<stdlib.h>
#include<iostream>
using namespace std;
bool G[30][30];
struct Point
{
int x,y;
void read()
{
scanf("%d %d",&x,&y);
}
};
Point rect[30][2];
Point num[30];
bool vis[30];
int link[30];
bool match(int x,int n)
{
for(int i=1;i<=n;i++)
{
if(G[x][i] && !vis[i])
{
vis[i]=1;
if(link[i]==-1 || match(link[i],n))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int Hungury(int n)
{
int ans=0;
memset(link,-1,sizeof link);
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
if(match(i,n))
ans++;
}
return ans;
}
int main()
{
int n,ca=0;
while(cin>>n&&n )
{
for(int i=1;i<=n;i++)
{
scanf("%d %d",&rect[i][0].x,&rect[i][1].x);
scanf("%d %d",&rect[i][0].y,&rect[i][1].y);
}
for(int i=1;i<=n;i++)
num[i].read();
memset(G,0,sizeof G);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(rect[i][0].x<num[j].x && num[j].x<rect[i][1].x
&&rect[i][0].y<num[j].y && num[j].y<rect[i][1].y)
G[j][i]=1;
}
}
printf("Heap %d\n",++ca);
bool fg=0;
if(Hungury(n)==n)
fg=1;
bool ff=0;
if(fg)
{
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
int tmp=link[i];
G[link[i]][i]=0;
link[i]=-1;
if(match(tmp,n))
{
G[tmp][i]=1;
continue;
}
if(ff)
printf(" ");
ff=1;
printf("(%c,%d)",i+'A'-1,tmp);
link[i]=tmp;
G[tmp][i]=1;
}
}
if(!ff)
printf("none");
puts("\n");
}
return 0;
}