题面点上方链接
本题需要用的芝士:二分图最大匹配的必须边。
分析:
根据题意,一个幻灯片覆盖的数字才可能是它自己的数字,明显是二分图最大匹配。
数字为左部点,幻灯片为右部点。(喜欢谁左谁右都行)
n不超过26,而且一个幻灯片只配对一个数字,
只需暴力枚举,若某个幻灯片覆盖了某个数字则连边,然后求最大匹配。
题目要求唯一的配对方案,也就是让我们判断匹配边是不是必须边,是必须边才输出方案。
有个坑点,是一个幻灯片都不能确定才输出“none”。
因为每个幻灯片上都标着它的顺序编号,所以肯定有完备匹配,用匈牙利算法(喜欢最大流也行啦)+Tarjan求强联通即可。
巨丑无比的代码:
#include<cstdio>
#include<cstring>
using namespace std;
int ri()
{
char c=getchar();int s=0,zf=1;
while(c<'0'||c>'9')
{
if(c=='-')zf=-1;
c=getchar();
}
while(c>='0'&&c<='9')s=(s<<1)+(s<<3)+c-'0',c=getchar();
return s*zf;
}
int mymin(int x,int y){return x<y?x:y;}
int n;
struct zb
{
int x,y;
}hdp[30][2];
struct bian
{
int y,next;
}a[2100];int last[60],len;
void ins(int x,int y)
{
a[++len].y=y;
a[len].next=last[x];last[x]=len;
}
int match[30];
bool chw[30];
bool find(int x)
{
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(!chw[y])
{
chw[y]=true;
if(match[y]==0||find(match[y]))
{
match[y]=x;
return true;
}
}
}
return false;
}
int dfn[60],low[60],id;
int bl[60],cnt;
int sta[60],top;
bool v[60];
void dfs(int x)
{
dfn[x]=low[x]=++id;
sta[++top]=x;v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if((x>n&&match[y]==x)||(x<=n&&match[x]!=y))continue;
if(dfn[y]==0)
{
dfs(y);
low[x]=mymin(low[x],low[y]);
}
else if(v[y])low[x]=mymin(low[x],dfn[y]);
}
if(dfn[x]==low[x])
{
int i;
cnt++;
do{
i=sta[top--];
v[i]=false;
bl[i]=cnt;
}while(i!=x);
}
}
int main()
{
int t=0;
while(++t)
{
n=ri();if(n==0)break;
for(int i=1;i<=n;i++)
{
hdp[i][0].x=ri();
hdp[i][1].x=ri();
hdp[i][0].y=ri();
hdp[i][1].y=ri();
}
memset(last,0,sizeof(last));len=0;
for(int i=1;i<=n;i++)
{
int x=ri(),y=ri();
for(int j=1;j<=n;j++)if(hdp[j][0].x<=x&&x<=hdp[j][1].x&&hdp[j][0].y<=y&&y<=hdp[j][1].y)ins(i+n,j),ins(j,i+n);
}
memset(match,0,sizeof(match));
printf("Heap %d\n",t);
for(int i=1;i<=n;i++)
{
memset(chw,false,sizeof(chw));
bool l=find(i+n);
}
memset(dfn,0,sizeof(dfn));
memset(bl,0,sizeof(bl));
memset(v,false,sizeof(v));
cnt=top=id=0;
for(int i=1;i<=2*n;i++)if(dfn[i]==0)dfs(i);
int ll=0;
for(int i=1;i<=n;i++)if(bl[i]!=bl[match[i]])ll=i;
if(ll==0)puts("none");
else
{
for(int i=1;i<=n;i++)if(bl[i]!=bl[match[i]])
{
printf("(%c,%d)",i+'A'-1,match[i]-n);
putchar(((i!=ll)?(' '):('\n')));
}
}
puts("");
}
return 0;
}
######千古神犇LKY,扑通扑通跪下来~QWQ
#####千古神犇LKY,扑通扑通跪下来~QWQ
####千古神犇LKY,扑通扑通跪下来~QWQ
###千古神犇LKY,扑通扑通跪下来~QWQ
##千古神犇LKY,扑通扑通跪下来~QWQ
#千古神犇LKY,扑通扑通跪下来~QWQ
千古神犇LKY,扑通扑通跪下来~QWQ
千古神犇LKY,扑通扑通跪下来~QWQ
千古神犇LKY,扑通扑通跪下来~QWQ
千古神犇LKY,扑通扑通跪下来~QWQ
千古神犇LKY,扑通扑通跪下来~QWQ