UVA663 Sorting Slides(烦人的幻灯片)
李教授将于今天下午做一次非常重要的演讲。不幸的是,他是一个非常不爱整洁的人,他把自己演讲要用的幻灯片随便堆在了一起。因此,演讲之前他不得不去整理这些幻灯片。作为一个讲求效率的学者,他希望尽可能简单地完成它。
题目描述:
教授这次演讲一共要用 n 张幻灯片,这 n 张幻灯片按照演讲要使用的顺序已经用数字 1~n 编了号。因为幻灯片是透明的,所以我们不能一下子看清每一个数字所对应的幻灯片。
现在我们用大写字母 A,B,C … 再次将幻灯片依次编号。你的任务是编写一个程序,把幻灯片的数字和字母编号对应起来,显然这种对应是唯一的;若出现多种对应的情况或是某些数字编号和字母编号对应不起来,我们称这种对应是无法实现的。
输入格式:
有多组测试数据。每组测试数据,第一行输入一个整数 n,表示有 n 张幻灯片,接下来 n 行,每行包括 4 个整数: x_min,x_max,y_min,y_max ,为幻灯片的坐标(幻灯片默认为矩形)。这 n 张幻灯片按其在输入文件中出现的顺序从前到后依次编号为 A,B,C …,再接下来的 n 行依次为 n 个数字编号的坐标 x,y (保证数字坐标不超出幻灯片的范围)。当 n 等于 0 时,输入结束。
输出格式:
对于每组测试数据,先输出测试数据的序号,若数据有解,按照字母顺序,依次输出每个字母所对应的数字编号,形如:(A,1) 。若无解,输出 none 。
注意:除最后一组数据外,每组数据在答案输出结束后要多输出一个空行
解析
第一次做到这么玄学的题,在《信息学奥赛一本通》拓扑排序一章找到这个习题(却发现标程都是错的),结果用二分图匹配做了出来
蒟蒻感觉思路不太好想,难度大概在蓝题~紫题。。
那是因为UVa输出换行空格万年老坑
#include<cstdio> #include<cstring> using namespace std; #define N 27 int vis[N],match[N],ans[N],x1[N],x2[N],y1[N],y2[N],n,T; bool g[N][N],flag; inline bool dfs(int x) { for (register int i=1; i<=n; i++) if (!vis[i] && g[x][i]) { vis[i]=1; if (!ans[i] || dfs(ans[i])) { ans[i]=x;//第 i 个幻灯片对应数字为 x return true; } } return false; } inline int find() {//求二分图最大匹配 int sum=0; memset(ans,0,sizeof ans); for (register int x=1; x<=n; x++){ memset(vis,0,sizeof vis); if (dfs(x)) sum++;// 总匹配数 } return sum; } int main() { while(~scanf("%d",&n) && n) { if (T) puts(""); printf("Heap %d\n",++T); memset(g,0,sizeof g); for (int i=1; i<=n; i++) scanf("%d%d%d%d",&x1[i],&x2[i],&y1[i],&y2[i]); for (int i=1,x,y; i<=n; i++) { scanf("%d%d",&x,&y); for (int j=1; j<=n; j++) if (x>=x1[j] && x<=x2[j] && y>=y1[j] && y<=y2[j]) g[i][j]=1;//如果数字在幻灯片范围之内的话则连边,有机会匹配 } int tot=find(),flag=0;
自此已求出当前的匹配,但程序还未结束,如果在此输出答案:
for (int i=1;i<=n;i++) printf("(%c,%d)",i-1+'A',ans[i]);
按照样例数据,你会发现第一组数据已有正确答案,而第二组数据不是none,而输出了匹配情况
这是因为题目还有一个要求:
若出现多种对应的情况,我们称这种对应是无法实现的。
第二组数据中A和B都可以匹配1和2中任意一个,所以对应不唯一
//接下来我们要去除这种情况 for (int j=1; j<=n; j++) for (int i=1;i<=n; i++) if (g[i][j]) { g[i][j]=0;//考虑依次删去每条边,如果有唯一对应,那么至少有一边删去后使匹配数减少 if (find()!=tot) { if (flag) printf(" "); else flag=1; printf("(%c,%d)",j-1+'A',i);//如果幻灯片 j 与 数字 i 是唯一搭配,直接输出 } g[i][j]=1; } if (!flag) printf("none");//如果删去任意一边匹配数都不变,则对应不唯一 puts("");//相当于printf("\n"); } return 0; }