hdu(3225) 求第k小匹配(09上海站F题)
来源:互联网 发布:知金教育怎么样 编辑:程序博客网 时间:2024/04/29 09:22
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3225
题意描述:给你M*N的格子,N种花,每个格子种一种花,每一行种N中不同的花且每一列不能有相同的花出现,现在要求增加一行后也满足这个条件,让你求出按字典序第k大的一种种法,如果小于k种,那么直接输出-1
分析:该行的每一个位置都可以种一些满足条件的花,可以这样建图,每一个位置可以和多种花连边,求第k完备匹配即是答案,那么怎么求第k小完备匹配呢??
这里我们就可以用搜索来解,按字典序进行搜索,枚举出一种情况就判断该情况是否是一个完备匹配,这样求出来的第k个即为答案,显然这题不会这么水,毕竟是个匹配有关的题目,所以一定会用到匹配的,这里我们就可以用匹配算法来进行剪枝,我们先求出一个完备匹配,然后搜索每个位置能够种的花,假设当前位k置种了花i,那么判断k+1--n位置能不能形成一个完备匹配(即能否种出满足条件的花),若能那么当前位置可以种该花,继续搜索,若不能这返回
详情见代码:
#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int N=300;bool vis[N][N];int g[N][N];int link[N];//link里面存放的是花对应放的位置的编号bool used[N];bool visit[N];int n,link1[N],k,num,res[N];bool find(int t,int limit)//找出比点得编号比limit大的匹配{ if(t<=limit)return false; int i; for(i=1;i<=n;i++) if(g[t][i]&&!used[i]) { used[i]=true; if(link[i]==-1||find(link[i],limit)) { link[i]=t; return true; } } return false;}bool check(int pid,int fid) //判断假设pid和fid匹配之后,看pid+1--n个位置是否能够形成完备匹配{ if(link[fid]==pid)return true; int i,j; for(i=1;i<=n;i++) { link1[i]=link[i]; if(link[i]==pid)j=i; } int t=link[fid]; link[fid]=pid; link[j]=-1; //将花fid和位置pid匹配,则与花原来匹配的位置则需从新匹配 memset(used,0,sizeof(used)); if(find(t,pid)) return true; else for(i=1;i<=n;i++) link[i]=link1[i]; return false;}bool dfs(int depth){ if(depth==n+1) { num++; if(num==k) return true; return false; } for(int i=1;i<=n;i++) if(!visit[i]&&g[depth][i]&&check(depth,i)) { visit[i]=true; res[depth]=i; if(dfs(depth+1))return true; visit[i]=false; } return false;}int main (){ int t,cas=1,m,i,j,x; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); memset(vis,0,sizeof(vis)); //vis[i][j]为1的时候表示第i行第j个位置种了第j种花 for(i=1;i<=m;i++) for(j=1;j<=n;j++) { scanf("%d",&x); vis[j][x]=true; } memset(g,0,sizeof(g)); for(j=1;j<=n;j++) for(i=1;i<=n;i++) if(!vis[i][j]) g[i][j]=1;//表示第j个位置可以放第i中花 printf("Case #%d:",cas++); memset(link,-1,sizeof(link)); for(i=1;i<=n;i++) { memset(used,0,sizeof(used)); if(!find(i,0)) break; } if(i<=n){printf(" -1\n");continue;} num=0; memset(visit,0,sizeof(visit)); bool tag=dfs(1); if(tag) for(i=1;i<=n;i++) printf(" %d",res[i]); else printf(" -1"); printf("\n"); } return 0;}
- hdu(3225) 求第k小匹配(09上海站F题)
- hdu 3225 Flowers Placement(字典序第k小的完美匹配)
- 【HDU】2665 求第k小的数
- 求第k小元素
- 计蒜客-求第k小
- 计蒜客-求第K小
- hdu 2104 K-th Number(静态求区间第k小+整体二分)
- hdu5008(后缀数组求第k小的字串)
- soj3102 O(n)求第k小的数
- 划分树(求区间第k小值)
- 线性时间求第k小(分治思想)
- 17AHU排位赛3 F题 (多路归并求第k大和)
- HDU-2639(01背包+求第k个最大值)
- 【算法题】BFPRT算法:求第K小或者第K大的数
- 快排划分思想的应用-求第k大数或者第k小的数(求前k大数或者前k小的数)
- 树状数组求第K小元素
- 【分治】求第k小值
- 快速排序求第K小
- NASM 纯汇编打造简单中文操作系统(2 init.asm初始化操作系统内存。进入32位保护模式)
- c++仿java简单封装
- 读写文件
- Linux常用命令总结1(用户操作相关)
- 使用Nginx代理模式,后端程序得到用户IP的方法
- hdu(3225) 求第k小匹配(09上海站F题)
- SQL养成一个好习惯是一笔财富
- HDU1520 Anniversary party
- 如何在EditText中设置固定图片——Android移动开发
- bioinformaition Plot tools
- Android学习五之Service
- 树形DP---hdu 1520 Anniversary Party
- IE6bug整理(hover a:hover) IE6 a:hover 无效
- 引用计数