HDU5727
2016-07-27 16:36
274 查看
Problem : Necklace
Source : 2016 Multi-University Training Contest 1
Description : 有一串项链,有2*N颗珠子,珠子有阴阳之分,各一半,同种类型的珠子不能项链,但是现在又有一些规则:有些阳珠子和阴珠子在一起就会使得阳珠子变暗,问你最少会有多少颗阳珠子变暗。
Solution : 全排列枚举+二分图最大匹配。讲道理,一开始我并不知道是用二分图来做的。知道用二分图做又不知道如何建图,知道看到了网上有人说全排列,我才有了灵感,我们知道,阴阳珠子的位置都是不固定的,那么我们就枚举固定阴珠子的位置。然后每个位置看能不能放阳珠子,如果能放就连边。最后求出最大匹配是表示有几个位置的阳珠子不会暗淡。最后直接维护一个最值就好了。下面一张图:
由于我一开始看到的解题报告是“环排”,也就是环排列,这是一个优化,n的环排列是(n−1)!,因为是环,所以环可以旋转,如果旋转后的环同原来的环一样,那么这两个环就是一个环。因此,我们不让它旋转,也就是固定一个位置,这里我选择固定1这个位置,后面的数进行全排列就好了。但是这个题不用环排也可以过,直接全排列也行的,不过时间比较危险。开始我一直过不去样例,原因是我建图的时候是[阴->阳],而开始一输入的时候是[阳->阴]。因此我调了下输入的位置就过了。下图中的TLE是因为一个小小的优化没有写,那就是
Code(C++) :
Source : 2016 Multi-University Training Contest 1
Description : 有一串项链,有2*N颗珠子,珠子有阴阳之分,各一半,同种类型的珠子不能项链,但是现在又有一些规则:有些阳珠子和阴珠子在一起就会使得阳珠子变暗,问你最少会有多少颗阳珠子变暗。
Solution : 全排列枚举+二分图最大匹配。讲道理,一开始我并不知道是用二分图来做的。知道用二分图做又不知道如何建图,知道看到了网上有人说全排列,我才有了灵感,我们知道,阴阳珠子的位置都是不固定的,那么我们就枚举固定阴珠子的位置。然后每个位置看能不能放阳珠子,如果能放就连边。最后求出最大匹配是表示有几个位置的阳珠子不会暗淡。最后直接维护一个最值就好了。下面一张图:
由于我一开始看到的解题报告是“环排”,也就是环排列,这是一个优化,n的环排列是(n−1)!,因为是环,所以环可以旋转,如果旋转后的环同原来的环一样,那么这两个环就是一个环。因此,我们不让它旋转,也就是固定一个位置,这里我选择固定1这个位置,后面的数进行全排列就好了。但是这个题不用环排也可以过,直接全排列也行的,不过时间比较危险。开始我一直过不去样例,原因是我建图的时候是[阴->阳],而开始一输入的时候是[阳->阴]。因此我调了下输入的位置就过了。下图中的TLE是因为一个小小的优化没有写,那就是
if(!ans)break;如果已经算出了最最小值,那么就不用再计算了,没有想到一个这样的语句居然能使TLE->187ms.
Code(C++) :
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <string> #include <vector> #define MIN(a,b) ((a)>(b)? (b):(a)) using namespace std; const int E=9+5; const int F=E*E; int N,M; int edge[E][E]; int belong[E]; bool used[E]; vector<int> map[E]; void init_vector() { for(int i=0;i<E;i++) map[i].clear(); } bool dfs(int s) { for(int i=0;i<map[s].size();i++){ int end=map[s].at(i); if(used[end]) continue; used[end]=true; if(belong[end]==-1||dfs(belong[end])){ d1fc belong[end]=s; return true; } } return false; } int main() { //freopen("in.data","r",stdin); while(~scanf("%d%d",&N,&M)){ memset(edge,true,sizeof(edge)); int a,b; for(int i=0;i<M;i++) scanf("%d%d",&a,&b), edge[b][a]=false; int ans=E; int h[E]={ 0,1,2,3,4,5,6,7,8,9, }; do{ init_vector(); memset(belong,-1,sizeof(belong)); for(int i=1;i<=N;i++) if(edge[h[1]][i]&&edge[h ][i]) map[1].push_back(i); for(int j=2;j<=N;j++) for(int i=1;i<=N;i++) if(edge[h[j]][i]&&edge[h[j-1]][i]) map[j].push_back(i); int sum=0; for(int i=1;i<=N;i++){ memset(used,false,sizeof(used)); if(dfs(i)) ++sum; } ans=MIN(N-sum,ans); if(!ans) break; }while(next_permutation(h+2,h+N+1)); \\next_permutation(h+1,h+N+1)也可以 printf("%d\n",ans); } return 0; }
相关文章推荐
- Codeforces Round #244 (Div. 2) E. Police Patrol(数学)
- Android梳理不常用widget篇
- js 生成二维码实例
- mysql -- 区分apk包中,java包,android包,第三方包的方法
- 实体引用
- 【转载】十条jQuery代码片段助力Web开发效率提升
- 看慕课节日祝福总结
- UVA 12105 Bigger is Better(数位DP)
- 六、数据库优化(上)——Mysql主从复制搭建
- GridView布局,自定义适配器,水平滚动
- 使用Lombok简化你的代码
- 一致性hash算法学习
- 拖拽回放
- [置顶] android 底层日志 开发框架 崩溃后进行记录 LogReport
- 使用NodeJS调用Dubbo工程
- Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)
- ListView
- hdu5754Life Winner Bo+博弈
- XZ_HTML5之HTML脚本、实体和URL
- JDBC获取数据表字段名、注释等信息