题意:有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 + 二进制法枚举子集)的更多相关文章

  1. UVA 818 Cutting Chains 切断圆环链 (暴力dfs)

    题意就是给一张无向图,去掉某些结点,然后连成一条链,问最少去掉几个结点. n很小n<=15,所以直接枚举2^15个状态就行啦. 链的条件是1.无环,2.没有度大于2的点,3.把n个散链连起来需要 ...

  2. UVA 818 Cutting Chains

    https://vjudge.net/problem/UVA-818 题意: 有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链 n<=15 因为n< ...

  3. UVA 818 Cutting Chains(状压 + 暴搜)题解

    题意:有1~n个小环,他们中的有些互相扣在一起,问你至少切开几个能把这写小环串成一条链 思路:还是太菜了,题目给的n<=15,显然可以暴力解决. 用二进制表示每个环切还是不切,然后搜索所有情况. ...

  4. UVa 11464 Even Parity (二进制法枚举)

    题意:给你一个n*n的01矩阵,让你把最少的0变成1,使得每个元素的上,下,左,右的元素(如果有的话)之和均为偶数. 析:最好想的的办法就是暴力,就是枚举每个数字是变还是不变,但是...时间复杂度也太 ...

  5. UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)

    题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的, ...

  6. UVA - 524 Prime Ring Problem(dfs回溯法)

    UVA - 524 Prime Ring Problem Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & % ...

  7. 算法笔记-- 二进制集合枚举子集 && 求子集和 && 求父集和

    枚举子集: 复杂度:O(2^k) )&s); 用sos dp求解子集和以及父集和 子集和: ; i <= k; i--) { ; mask < (<<k); mask+ ...

  8. UVa 818 切断圆环链(dfs+二进制枚举)

    https://vjudge.net/problem/UVA-818 题意:有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3 ...

  9. UVa 818Cutting Chains (暴力dfs+位运算+二进制法)

    题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上 ...

随机推荐

  1. 「AT1983 BBQ Hard」

    呦,来一次久违的BBQ吧! AT题...日本的题库质量一向很高 这题是有关组合数的DP... 前置芝士 快速计算组合数,具体还是自行百度. 膜域下的除法. 具体做法 题目中的问题: \(\sum_{i ...

  2. Day2-L-棋盘问题-POJ1321

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. ...

  3. Flask与Django哪个更好更实用呢?砖家是这么认为的

        这一周我打算做一个 Flask 教程.本文先把 Flask 和 Django 做一个比对,因为我对这两个 Python Web 框架都有实际的开发经验.希望我可以帮助您选择学习哪个框架,因为学 ...

  4. 如何使用Nexus搭建Maven私服

    如何使用Nexus搭建Maven私服 听语音 | 浏览:47 | 更新:2016-09-29 10:22 1 2 3 4 5 6 7 分步阅读 一键约师傅 百度师傅最快的到家服务,最优质的电脑清灰! ...

  5. 前端学习笔记系列一:3 Vue中的nextTick

    一.示例 先来一个示例了解下关于Vue中的DOM更新以及nextTick的作用. 模板 <div class="app"> <div ref="msgD ...

  6. 使用 esxcli storage vmfs unmap 命令在精简置备的 LUN 上回收 VMFS 删除的块

    官方原文链接: https://kb.vmware.com/s/article/2057513?lang=zh_CN 本文介绍如何通过运行 esxcli storage vmfs unmap 命令回收 ...

  7. py交易

    下载之后发现是pyc文件,反编译一下 网站:https://tool.lu/pyc/ 发现其实就是base64转换为16进制,然后减去16再和32异或,就可以得到答案了 nctf{d3c0mpil1n ...

  8. 冰蝎动态二进制加密WebShell特征分析

    概述 冰蝎一款新型加密网站管理客户端,在实际的渗透测试过程中有非常不错的效果,能绕过目前市场上的大部分WAF.探针设备.本文将通过在虚拟环境中使用冰蝎,通过wireshark抓取冰蝎通信流量,结合平时 ...

  9. 洛谷 P2634 聪聪可可

    题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...

  10. Day6 - J - Cartesian Tree POJ - 2201

    Let us consider a special type of a binary search tree, called a cartesian tree. Recall that a binar ...