真是不看题解,怎么也搞不清楚题目要求什么。。先说建边还是比较好建的,判断点是否在幻灯片的范围内,在就连一条边。一直以为必须要每个页码都能匹配上幻灯片,随便匹配,只要能给页码分配个幻灯片就行,才能输出结果呢。直到wa到怀疑人生,搜了下题解,原来只要有某个页码能完全确定匹配上某一页幻灯片,输出就行了。
因为页码本来就在幻灯片上,所以最大匹配肯定是就是幻灯片个数,即完美匹配。
先求出最大匹配,判断最大匹配是不是完美匹配,不是的话,就none了,是的话,就挨个删边,删掉每个边后,再跑一遍最大匹配,如果最大匹配不变,那么那条边就是不确定的。如果最大匹配变小了,就说明那条边是唯一确定的,输出就行了。
#include <stdio.h>
#include <string.h>
#include <set>
#include <utility>
using namespace std;
const int MAXN = 30;
int uN,vN;//u,v的数目,使用前面必须赋值
int g[MAXN][MAXN];//邻接矩阵
int linker[MAXN];
int path[MAXN];
bool used[MAXN];
bool dfs(int u)
{
for(int v = 0; v < vN; v++)
if(g[u][v] && !used[v])
{
used[v] = true;
if(linker[v] == -1 || dfs(linker[v]))
{
linker[v] = u;
return true;
}
}
return false;
}
int hungary()
{
int res = 0;
memset(linker,-1,sizeof(linker));
for(int u = 0; u < uN; u++)
{
memset(used,false,sizeof(used));
if(dfs(u))res++;
}
return res;
}
struct PPT
{
int xmin,xmax,ymin,ymax,id;
bool operator==(const PPT& b) const
{
return xmin == b.xmin && xmax == b.xmax && ymin == b.ymin && ymax == b.ymax;
}
bool contain(int x, int y)
{
return x >= xmin && x <= xmax && y >= ymin && y <= ymax;
}
} ppt[MAXN];
int main()
{
int n,x,y,cnt = 0;
while(scanf("%d",&n) && n)
{
++cnt;
uN = vN = n;
memset(g,0,sizeof(g));
for(int i = 0; i < n; ++i)
{
scanf("%d %d %d %d",&ppt[i].xmin,&ppt[i].xmax,&ppt[i].ymin,&ppt[i].ymax);
ppt[i].id = i;
}
for(int i = 0; i < n; ++i)
{
scanf("%d %d",&x,&y);
for(int j = 0; j < n; ++j)
{
if(ppt[j].contain(x,y))
g[i][ppt[j].id] = 1;
}
}
printf("Heap %d\n",cnt);
int res = hungary();
if(res != n)
{
printf("none\n\n");
continue;
}
bool flag = true;
for(int i = 0; i < n; ++i) path[i] = linker[i];
for(int i = 0; i < n; ++i)
{
if(path[i] == -1) continue;
g[path[i]][i] = 0;
int t = linker[i];
res = hungary();
g[path[i]][i] = 1;
if(res != n)
{
printf("(%c,%d) ",i+'A',path[i]+1);
flag = false;
}
}
if(flag)
{
printf("none\n\n");
continue;
}
printf("\n\n");
}
return 0;
}