题意:
如图所示:A包含1 2 4三点,即他可以A和1 2 3 匹配
B可以和1 3 匹配,以此类推
问有多少字母只能和某一个数字匹配,才能使匹配数最大?
思路:
先建图,二分图,枚举二分图的每一条边,如果去掉这条边之后,匹配数减少,就说明该字母只能和该数字匹配。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
const int maxn=1000+100;
struct node
{
int sx,sy,ex,ey;
}a[maxn*maxn*4+100];
struct nodee
{
char ch;
int x;
}b[maxn*4+100];
int head[maxn],cnt=0;
int cx[maxn],cy[maxn],inpath[maxn];
int mapp[maxn][maxn];
int n;
int dfs(int u)
{
for(int i=1;i<=n;i++)
{
if(mapp[u][i]==1)
{
if(!inpath[i])
{
inpath[i]=1;
if(cy[i]==-1||dfs(cy[i]))
{
cy[i]=u;
cx[u]=i;
return 1;
}
}
}
}
return 0;
}
int zyz()
{
for(int i=1;i<=n;i++)
{
cx[i]=-1;
}
for(int j=1;j<=n;j++)
{
cy[j]=-1;
}
int res=0;
for(int i=1;i<=n;i++)
{
if(cx[i]==-1)
{
memset(inpath,0,sizeof(inpath));
res+=dfs(i);
}
}
return res;
}
int cmp(nodee aa,nodee bb)
{
return aa.ch<bb.ch;
}
int main ()
{
int icase=0;
while(~scanf("%d",&n))
{
++icase;
if(n==0)
{
break;
}
printf("Heap %d\n",icase);
memset(mapp,0,sizeof(mapp));
memset(head,-1,sizeof(head));
cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a[i].sx,&a[i].ex,&a[i].sy,&a[i].ey);
}
for(int i=1;i<=n;i++)
{
int xx,yy;
scanf("%d%d",&xx,&yy);
for(int j=1;j<=n;j++)
{
//printf("%d %d %d %d\n",a[j].sx,a[j])
if(xx>=a[j].sx&&xx<=a[j].ex&&yy>=a[j].sy&&yy<=a[j].ey)
{
mapp[j][i]=1;
//printf("%d\n",mapp[i][j]);//
}
}
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",mapp[i][j]);
}
printf("\n");
}*/
int answer=zyz();
//printf("%d\n",answer);
int cntt=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(mapp[i][j]==1)
{
mapp[i][j]=0;
int ans=zyz();
mapp[i][j]=1;
if(answer!=ans)
{
b[++cntt].ch='A'+i-1;
b[cntt].x=j;
}
}
}
}
sort(b+1,b+1+cntt,cmp);
if(cntt==0)
{
printf("none\n\n");
continue;
}
for(int i=1;i<=cntt;i++)
{
if(i!=1)
{
printf(" (%c,%d)",b[i].ch,b[i].x);
}
else
{
printf("(%c,%d)",b[i].ch,b[i].x);
}
}
printf("\n");
printf("\n");
}
}