可以直接模拟这个过程,可知如果当前有点仅属于某个幻灯片,那么便可确定此点和此幻灯片的匹配关系,反之如果有幻灯片只包括某个点,也可确定此幻灯片和此点的匹配关系,如果没有这两种情况的话,剩下的就不能确定了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#define LL long long
#define myabs(x) ((x)>0?(x):(-(x)))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=500+10;
struct node
{
int xmin,xmax,ymin,ymax;
};
node slide[maxn];
int re[maxn],vis2[maxn];
int g1[maxn][maxn],g2[maxn][maxn];
int n,m;
void solve()
{
memset(re,0,sizeof(re));
int flag=1;
int i,j,k;
while(flag)
{
flag=0;
for(i=1;i<=n;i++)
{
if(g1[i][0]==1)
{
flag=1;
for(j=1;j<=n;j++) if(g1[i][j]) break;
re[i]=j;
g2[j][0]=0;//相当于vis赋为1
for(k=1;k<=n;k++)
{
if(g1[k][j])
{
g1[k][0]--;
g1[k][j]=0;
}
}
}
}
for(i=1;i<=n;i++)
{
if(g2[i][0]==1)
{
flag=1;
for(j=1;j<=n;j++) if(g2[i][j]) break;
re[j]=i;
g1[j][0]=0;
for(k=1;k<=n;k++)
{
if(g2[k][j])
{
g2[k][j]=0;
g2[k][0]--;
}
}
}
}
}
}
int main()
{
int cas=0;
while(~scanf("%d",&n)&&n)
{
int i,j,u,v;
for(i=1;i<=n;i++)
scanf("%d%d%d%d",&slide[i].xmin,&slide[i].xmax,&slide[i].ymin,&slide[i].ymax);
int x,y,flag=1;
memset(g1,0,sizeof(g1));
memset(g2,0,sizeof(g2));
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
for(j=1;j<=n;j++)
{
if(x>slide[j].xmin&&x<slide[j].xmax&&y>slide[j].ymin&&y<slide[j].ymax)
{
g1[j][i]=g2[i][j]=1;
g1[j][0]++;
g2[i][0]++;
}
}
}
printf("Heap %d\n",++cas);
solve();
for(i=1;i<=n;i++)
{
if(re[i])
{
if(flag)
{
flag=0;
printf("(%c,%d)",i-1+'A',re[i]);
}
else printf(" (%c,%d)",i-1+'A',re[i]);
}
}
if(flag) printf("none");
printf("\n\n");
}
return 0;
}
也可用二分图的匹配来做。首先求出一个最大匹配,然后去看每个点是否必须和他匹配的那个点匹配,就是删除两点的边,看是否还能构成匹配数为n的最大匹配。这里不需要从头再算一次增广路算法。因为删去此边之后,对其他点的匹配没有影响。增广路算法对点的增广不分先后 ,那么可以先去增广匹配其他的点,显然,其他的点肯定能增广匹配,而且其增广匹配的一种结果已经得出,不就是之前第一次求出的匹配关系吗,这些关系没有变,所有就直接增广当前删去的边所对应的点就可以了。但是增广的过程中就不要修改left值了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#define LL long long
#define myabs(x) ((x)>0?(x):(-(x)))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=500+10;
struct node
{
int xmin,xmax,ymin,ymax;
};
node slide[maxn];
int con[maxn][maxn];
int g[maxn][maxn];
int leftp[maxn],vis[maxn];
int n,m;
int omg;
int dfs(int u)
{
int i;
for(i=1;i<=n;i++)
{
if(g[u][i]&&!vis[i])
{
vis[i]=1;
if(!leftp[i]||dfs(leftp[i]))
{
if(omg)leftp[i]=u;/////////////////注意omg的使用
return 1;
}
}
}
return 0;
}
int solve()
{
omg=1;/////////////////////////////////
int u,v;
int sum=0;
for(u=1;u<=n;u++)
{
memset(vis,0,sizeof(vis));
if(dfs(u))
sum++;
}
return sum;
}
int main()
{
int cas=0;
while(~scanf("%d",&n)&&n)
{
int i,j,u,v;
memset(g,0,sizeof(g));
memset(leftp,0,sizeof(leftp));
memset(con,0,sizeof(con));
for(i=1;i<=n;i++)
scanf("%d%d%d%d",&slide[i].xmin,&slide[i].xmax,&slide[i].ymin,&slide[i].ymax);
int x,y,flag=1;
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
for(j=1;j<=n;j++)
if(x>=slide[j].xmin&&x<=slide[j].xmax&&y>=slide[j].ymin&&y<=slide[j].ymax)
g[i][j]=1;
}
printf("Heap %d\n",++cas);
solve();
int tem;
omg=0;
for(i=1;i<=n;i++)
{
tem=leftp[i];
leftp[i]=0;
g[tem][i]=0;
memset(vis,0,sizeof(vis));
if(!dfs(tem))
{
if(flag)
{
flag=0;
printf("(%c,%d)",i-1+'A',tem);
}
else printf(" (%c,%d)",i-1+'A',tem);
}
leftp[i]=tem;
g[tem][i]=1;
}
if(flag) printf("none");
printf("\n\n");
}
return 0;
}