UVa 818Cutting Chains (暴力dfs+位运算+二进制法)
题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链。
析:刚开始看的时候,确实是不会啊。。。。现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上的题解,大神们的代码就是不一样,
但还是看了好久才看懂。首先是用二进制法进行暴力,因为 n 最大才是15,不会超时的,然后就是在暴力时判断打开这些环时,剩下的是不是还存在环,
如果存在那么不是不行的,然后再判断是不是有的环有两个分支以上,因为一个环如果成链那么最多只有两个分支,所以多于两个的也是不对的,最后,
还要判断打开的环是不是够用,什么意思?你想啊,如果打开的环只有2个,还需要连接的片段环有3个,那么正好,可以用这两个环把它们串起来,
但是片段环多于3个了,那么就不够了,总有几个是连不上的,所以还要满足这个条件,打开的环数要大于等于需要连接的片段减1.剩下的就是怎么判断
成环和分支大于两个了,先说怎么判断怎么计算分支大于两个,在暴力的时候,可以单独计算除了要打开的环并且和它连接的环的数量,如果多于2个,
那么就是分支大于2,再说怎么判断成环,很明显用dfs,从一个环出发,看看能不能再搜回来,如果能那么就是有环,最后是计算,打开了多少环,
这个最简单的是再单独暴力一下,找到一个就加1,最后算出来,当然可以用递归+位运算,就是一个数的二进制中1的数量,可以用按位与进行计算。
但我的代码效率不高,210ms,有点慢。。。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring> using namespace std;
const int maxn = 15 + 5;
int n, num;
int G[maxn][maxn], vis[maxn]; bool branch(int s){//查找分支是多少
for(int i = 0; i < n; ++i){
if(s & (1<<i)) continue;//要打开的环
int cnt = 0;
for(int j = 0; j < n; ++j){
if(s & (1<<j)) continue;//这是要打开的环,不能计算
if(G[i][j]) ++cnt;//如果其他环与其相连接,就加1
}
if(cnt > 2) return true;//如果大于2,直接结束
}
return false;
} bool dfs(int s, int now, int fa){//now 表示当前的环是哪个,fa表示上一环是哪个,因为在搜索的时候不能搜自己
vis[now] = 1;
for(int i = 0; i < n; ++i){
if((s & (1<<i)) || !G[now][i] || i == fa) continue;//如果是打开的环或没有连接或者是自己,就跳过
if(vis[i] || dfs(s, i, now)) return true;//如果曾经访问过,也就是又找回来了。或者有环,直接返回
}
return false;
} bool circle(int s){//判断是不是有环
for(int i = 0; i < n; ++i){
if((s & (1<<i)) || vis[i]) continue;//是打开的环或者是已经访问的环
++num;
if(dfs(s, i, -1)) return true;//如果有环直接返回
}
return false;
} int cal(int s){ return s == 0 ? 0 : cal(s/2) + (s&1); }//计算要打开的环的数量 int solve(){
int ans = n-1;//最多就是打开n-1个
for(int i = 0; i < (1 << n); ++i){
memset(vis, 0, sizeof(vis));
num = 0;
if(branch(i) || circle(i)) continue;//如果有环或者是分支大于2个
if(cal(i) >= num-1) ans = min(ans, cal(i));//如果能够连起来,就更新ans
}
return ans;
} int main(){
// freopen("in.txt", "r", stdin);
int kase = 0;
while(scanf("%d", &n) == 1 && n){
int u, v;
memset(G, 0, sizeof(G));
while(scanf("%d %d", &u, &v) == 2 && u+v > 0){
G[u-1][v-1] = 1; G[v-1][u-1] = 1;
} printf("Set %d: Minimum links to open is %d\n", ++kase, solve());
}
return 0;
}
UVa 818Cutting Chains (暴力dfs+位运算+二进制法)的更多相关文章
- uva 10718 Bit Mask (位运算)
uva 10718 Bit Mask (位运算) Problem A Bit Mask Time Limit 1 Second In bit-wise expression, mask is a ...
- Codeforces Round #320 (Div. 2) [Bayan Thanks-Round] A. Raising Bacteria【位运算/二进制拆分/细胞繁殖,每天倍增】
A. Raising Bacteria time limit per test 1 second memory limit per test 256 megabytes input standard ...
- UVA - 13022 Sheldon Numbers(位运算)
UVA - 13022 Sheldon Numbers 二进制形式满足ABA,ABAB数的个数(A为一定长度的1,B为一定长度的0). 其实就是寻找在二进制中满足所有的1串具有相同的长度,所有的0串也 ...
- UVA 10718 Bit Mask 贪心+位运算
题意:给出一个数N,下限L上限U,在[L,U]里面找一个整数,使得N|M最大,且让M最小. 很明显用贪心,用位运算搞了半天,样例过了后还是WA,没考虑清楚... 然后网上翻到了一个人家位运算一句话解决 ...
- luogu P2114 [NOI2014]起床困难综合症 位运算 二进制
建议去uoj那里去测,数据比较强 位运算的题目,就得一位一位的分开考虑 然后枚举初始值的最高位是0 是1 的最终攻击 (二进制内)最高位是1肯定比次位是1次次位是1次次次位是1···的大吧,显然 然后 ...
- UVa 1590 IP网络(简单位运算)
Description Alex is administrator of IP networks. His clients have a bunch of individual IP addres ...
- 数独求解问题(DFS+位运算优化)
In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For exa ...
- SRM331-CarolsSinging(暴力,位运算)
Problem Statement When the Christmas dinner is over, it's time to sing carols. Unfortunately, not al ...
- UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)
题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的, ...
随机推荐
- java局部变量和临时变量
局部变量:temp=1, 临时变量:return a+b 临时变量会有一点的性能优势 局部变量会比成员变量和静态成员变量有优势,改进的方法是吧成员变量和静态成员变量赋值在局部变量:https://bl ...
- IntelliJ IDEA 基础设置
原文地址:IntelliJ IDEA 基础设置 博客地址:http://www.extlight.com 一.前言 IDEA 全称 IntelliJ IDEA,是java语言开发的集成环境,Intel ...
- erp中三大订单CO、PO、MO
ERP即 企业资源计划 (Enterprise Resource Planning),由美国 Gartner Group 公司于1990年提出. ERP系统是指建立在信息技术基础上,以系统化的管理思想 ...
- 闲扯淡笔记 - Web的历史
这里的Web指的是万维网,就是World Wide Web. 文档和静态资源 通过URL组织 Tim Berners Lee (TimBL) 于1989发明这个概念,这丫55年出生,和我父亲一般大. ...
- linux 线程的同步 三 (内存信号量的使用)
信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过是同步的对象不同而已.但是下面介绍的信号量的接口是用于线程的信号量,注意不要跟用于进程间通信的信号量混淆,关于用于进程间通 ...
- WebDriverException: Message: 'phantomjs.exe' executable needs to be in PATH.
本文转载自:http://blog.csdn.net/sinat_36764186/article/details/55520444 网上的某测试代码: from selenium import we ...
- 汇编_指令_JMP
JMP指令 JMP是汇编语言中的无条件跳转指令.无条件跳转指令可转到内存中任何程序段.转移地址可在指令中给出,也可以在寄存器中给出,或在储存器中指出. 中文名:无条件跳转指令 外文名:JMP 和调用指 ...
- HDU 1717 小数化分数2(最大公约数)
小数化分数2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- [html][LigerUI]使用示例
<link href="Source/lib/ligerUI/skins/Aqua/css/ligerui-all.css" rel="stylesheet&quo ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #1 如何获取Linux内核
HACK #1 如何获取Linux内核 本节介绍获取Linux内核源代码的各种方法.“获取内核”这个说法看似简单,其实Linux内核有很多种衍生版本.要找出自己想要的源代码到底是哪一个,必须首先理解各 ...