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 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上 ...
随机推荐
- CSP-S 2019 复赛游记
自闭游记 >_< Day 0 随便敲了一些板子 当然打了摆. 奶人的话写满了俩黑板啊,没人奶我可海星. 晚上没怎么打摆,随便敲了几道板子,然后很早就回去睡了. Day 1 平静地出发了.. ...
- IdentityServer4专题之三:OAuth、SSO和OpenID
一.oauth 典型案例:如果一个用户R拥有两项服务:一项服务是图片在线存储服务A,另一个是图片在线打印服务B.由于服务A与服务B是由两家不同的服务提供商提供的,所以用户在这两家服务提供商的网站上各自 ...
- java实现在线预览 - -之poi实现word、excel、ppt转html
简介 java实现在线预览功能是一个大家在工作中也许会遇到的需求,如果公司有钱,直接使用付费的第三方软件或者云在线预览服务就可以了,例如永中office.office web 365(http://w ...
- POJ 3267:The Cow Lexicon 字符串匹配dp
The Cow Lexicon Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8905 Accepted: 4228 D ...
- R 对数变换 《回归分析与线性统计模型》page103
BG:在box-cox变换中,当λ = 0时即为对数变换. 当所分析变量的标准差相对于均值而言比较大时,这种变换特别有用.对数据作对数变换常常起到降低数据波动性和减少不对称性的作用..这一变换也能有效 ...
- Redis详解(五)——主从复制
Redis详解(五)--主从复制 面临问题 机器故障.我们部署到一台 Redis 服务器,当发生机器故障时,需要迁移到另外一台服务器并且要保证数据是同步的.而数据是最重要的,如果你不在乎,基本上也就不 ...
- 051、Java中使用while循环实现1~100的累加
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 5.Linux解决Device eth0 does not seem to be present
Linux操作系统排除故障 导入vixualbox的虚拟机voa文件到另外一台电脑,需要检查如下信息 修改虚拟机软件网络设置 重启Linux操作系统 shutdown -h now reboot se ...
- python scipy优化器模块(optimize)
pyhton数据处理与分析之scipy优化器及不同函数求根 1.Scipy的优化器模块optimize可以用来求取不同函数在多个约束条件下的最优化问题,也可以用来求取函数在某一点附近的根和对应的函数值 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-road
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...