UVA - 818 Cutting Chains(切断圆环链)(dfs + 二进制法枚举子集)
题意:有n个圆环(n<=15),已知已经扣在一起的圆环,现在需要打开尽量少的圆环,使所有圆环可以组成一条链。
分析:因为不知道要打开哪个环,如果列举所有的可能性,即枚举打开环的所有子集,最多才2^15,即32768。
1、二进制法生成打开环的所有子集
2、枚举每一种子集,环打开后,此环就是孤立的,剩下的环也不与之相连,若剩下的环满足下列所有条件,则这种子集成立,进而最终比较打开环的最少个数。
(1)每个环与之相连的环的个数不超过2。
(2)剩下的环里没有圈,dfs判圈,连通块涂色。
(3)上述处理后,剩下的环形成了几条链状的连通块,通过打开的环将这些连通块连接。所以需要满足打开环的个数大于等于连通块个数减1。
#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {, , -, , -, -, , };
const int dc[] = {-, , , , -, , -, };
const int MOD = 1e9 + ;
const double pi = acos(-1.0);
const double eps = 1e-;
const int MAXN = + ;
const int MAXT = + ;
using namespace std;
set<int> s[];
int n;
int vis[];
int mark[];
bool flag;
void dfs(int x, int cnt, int fa){//fa是指向当前连通块的来源
if(flag) return;
if(mark[x] == cnt){
flag = true;//如果要染色的连通块已有颜色,则代表有圈
return;
}
mark[x] = cnt;
for(set<int>::iterator it = s[x].begin(); it != s[x].end(); ++it){
if(!vis[*it] && *it != fa){
dfs(*it, cnt, x);
}
}
}
bool judge(int num){
//判断剩下的环与几个环连着
for(int i = ; i <= n; ++i){
if(!vis[i]){
int cnt = ;
for(set<int>::iterator it = s[i].begin(); it != s[i].end(); ++it){
if(!vis[*it]) ++cnt;
}
if(cnt > ) return false;
}
}
//dfs判断剩下的环里有无圈,连通块涂色
memset(mark, , sizeof mark);
int cnt = ;//连通块个数
flag = false;
for(int i = ; i <= n; ++i){
if(!vis[i] && !mark[i]){
++cnt;
dfs(i, cnt, -);//cnt连通块涂色编号
}
if(flag) return false;
}
return num >= cnt - ;//如果打开环的个数大于等于连通块个数减1才成立
}
void solve(int kase){
int ans = INT_M_INF;
for(int i = ; i < ( << n); ++i){
memset(vis, , sizeof vis);
int cnt = ;//打开环的个数
for(int j = ; j < n; ++j){
if(i & ( << j)){
vis[j + ] = ;//下标为1~n
++cnt;
}
}
if(judge(cnt)) ans = Min(ans, cnt);
}
printf("Set %d: Minimum links to open is %d\n", kase, ans);
}
int main(){
int kase = ;
while(scanf("%d", &n) == ){
if(!n) return ;
for(int i = ; i < ; ++i) s[i].clear();
int x, y;
while(scanf("%d%d", &x, &y) == ){
if(x == - && y == -) break;
s[x].insert(y);
s[y].insert(x);
}
++kase;
solve(kase);
}
return ;
}
UVA - 818 Cutting Chains(切断圆环链)(dfs + 二进制法枚举子集)的更多相关文章
- UVA 818 Cutting Chains 切断圆环链 (暴力dfs)
题意就是给一张无向图,去掉某些结点,然后连成一条链,问最少去掉几个结点. n很小n<=15,所以直接枚举2^15个状态就行啦. 链的条件是1.无环,2.没有度大于2的点,3.把n个散链连起来需要 ...
- UVA 818 Cutting Chains
https://vjudge.net/problem/UVA-818 题意: 有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链 n<=15 因为n< ...
- UVA 818 Cutting Chains(状压 + 暴搜)题解
题意:有1~n个小环,他们中的有些互相扣在一起,问你至少切开几个能把这写小环串成一条链 思路:还是太菜了,题目给的n<=15,显然可以暴力解决. 用二进制表示每个环切还是不切,然后搜索所有情况. ...
- UVa 11464 Even Parity (二进制法枚举)
题意:给你一个n*n的01矩阵,让你把最少的0变成1,使得每个元素的上,下,左,右的元素(如果有的话)之和均为偶数. 析:最好想的的办法就是暴力,就是枚举每个数字是变还是不变,但是...时间复杂度也太 ...
- UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)
题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的, ...
- UVA - 524 Prime Ring Problem(dfs回溯法)
UVA - 524 Prime Ring Problem Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & % ...
- 算法笔记-- 二进制集合枚举子集 && 求子集和 && 求父集和
枚举子集: 复杂度:O(2^k) )&s); 用sos dp求解子集和以及父集和 子集和: ; i <= k; i--) { ; mask < (<<k); mask+ ...
- UVa 818 切断圆环链(dfs+二进制枚举)
https://vjudge.net/problem/UVA-818 题意:有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3 ...
- UVa 818Cutting Chains (暴力dfs+位运算+二进制法)
题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上 ...
随机推荐
- 073、Java面向对象之利用构造方法为属性赋值
01.代码如下: package TIANPAN; class Book { // 定义一个新的类 private String title; // 书的名字 private double price ...
- 安装oracle客户端后,怎样设置电脑的环境变量?
安装配置参考: http://www.haodaima.net/art/2854001 设置环境变量(修改PATH和TNS_ADMIN环境变量): 对于NLS_LANG环境变量, 最好设置成和数据库端 ...
- 机器学习、深度学习中的信息熵、相对熵(KL散度)、交叉熵、条件熵
信息熵 信息量和信息熵的概念最早是出现在通信理论中的,其概念最早是由信息论鼻祖香农在其经典著作<A Mathematical Theory of Communication>中提出的.如今 ...
- eot文件
*.eot文件 是一种压缩字库,目的是解决在网页中嵌入特殊字体的难题2.在网页中嵌入的字体只能是 OpenType 类型,其他类型的字体只有转换成 OpenType 类型(eot格式)的字体才能在网页 ...
- Windows 10工程版本泄露全新设计的操作中心圆角样式
早些时候微软错误地向Windows 10所有测试通道推送内部工程版本,该版本构建后尚未经过微软内部测试. 当然本身微软也没准备推送所以该版本里很多新功能未被关闭,而成功升级的用户则可以立即查看这些功能 ...
- pt-archiver 归档数据
pt-archiver 参数说明pt-archiver是Percona-Toolkit工具集中的一个组件,是一个主要用于对MySQL表数据进行归档和清除工具.它可以将数据归档到另一张表或者是一个文件中 ...
- loadBeanDefinitions方法源码跟踪(一)
看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractBeanDe ...
- [Codeforces]1263B PIN Code
题目 A PIN code is a string that consists of exactly 444 digits. Examples of possible PIN codes: 70137 ...
- .net core文件系统简介
在asp.net core程序中,我们可以通过如下代码开启对Web 根目录内的文件静态访问功能: app.UseStaticFiles(); 如果要提供更高级的选项,例如:将其它的物理文件夹下的文件作 ...
- dataGridView与数据源dataTable同步排序
private void dataGridView1_Sorted(object sender, EventArgs e) { string _sortStr ...