UVa 818 切断圆环链(dfs+二进制枚举)
https://vjudge.net/problem/UVA-818
题意:有n个圆环,其中有一些已经扣在了一起。现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3,4-5,则需要打开一个圆环,如圆环4,然 后用它穿过圆环3和圆环5后再次闭合4,就可以形成一条链:1-2-3-4-5。
思路:从n个圆环中任意选择圆环,这就是枚举子集。所以这道题目可以用二进制枚举来做。
那么如何判断当前打开圆环是可行的呢?在去除打开的圆环后需要判断:
①:每个圆环的分支数都必须小于等于2,大于2个肯定就不能成为单链了。
②:不能存在环。
③:连通分支数-1不能大于打开圆环数。
判断是否存在圆环和连通分支数都可以用dfs来实现。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std; int n,cnt,number;
int map[][];
int vis[];
int ans; bool two(int s) //判断是否有分支数大于2的圆环
{
for (int i = ; i < n; i++)
{
int cnt = ; //记录分支数
for (int j = ; j < n; j++)
{
//如果圆环i和j连通并且没有打开i或j时,i圆环的分支数+1
if (map[i][j] && !(s&( << i)) && !(s & << j))
{
cnt++;
if (cnt == ) return true;
}
}
}
return false;
} bool dfs(int x,int f,int s) //判断是否有回路存在
{
vis[x]=;
for (int i = ; i < n; i++)
{
if (map[x][i])
{
if (i == f || (s&( << i))) continue; //如果i是上一次访问的圆环或者i圆环被打开,进行下一次判定
if (vis[i]) return true; //存在回路
if (dfs(i, x, s)) return true;
}
}
return false;
} bool circle(int s)
{
memset(vis, , sizeof(vis));
for (int i = ; i < n; i++)
{
if (!vis[i] && !(s & ( << i)))
{
number++; //连通分量数+1
if (dfs(i , -, s)) return true;
}
}
return false;
} int calc(int s) //计算出打开圆环的个数
{
int cnt = ;
for (int j = ; j < n; j++)
{
if (s&( << j)) cnt++;
}
return cnt;
} void solve()
{
ans = ;
for (int i = ; i < ( << n); i++) //二进制枚举打开圆环的情况
{
number = ;
if (two(i) || circle(i)) continue; //如果不行,进行下一次判断,如果不存在两个分支或回路,则正好计算出了连通分支数
int count = calc(i);
if (number - <= count) ans = min(ans, count); //连通分支数-1不能多于打开的圆环数
}
} int main()
{
//freopen("D:\\txt.txt", "r", stdin);
int a, b, kase=;
while (cin >> n && n)
{
memset(map, , sizeof(map));
while (cin >> a >> b && a != - && b != -)
{
map[a-][b-] = ;
map[b-][a-] = ;
}
solve();
cout<<"Set "<<++kase<<": Minimum links to open is "<<ans<<endl;
}
return ;
}
UVa 818 切断圆环链(dfs+二进制枚举)的更多相关文章
- UVA.11806 Cheerleaders (组合数学 容斥原理 二进制枚举)
UVA.11806 Cheerleaders (组合数学 容斥原理 二进制枚举) 题意分析 给出n*m的矩形格子,给出k个点,每个格子里面可以放一个点.现在要求格子的最外围一圈的每行每列,至少要放一个 ...
- poj3279(dfs+二进制枚举思路)
题意转载自https://www.cnblogs.com/blumia/p/poj3279.html 题目属性:DFS 相关题目:poj3276 题目原文:[desc]Farmer John know ...
- UVA 1151二进制枚举子集 + 最小生成树
题意:平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此, 你可以新建一些边,费用等于两个端点的欧几里得距离的平方.另外还有q(0<=q<=8)个套餐(数 ...
- 紫书 例题 11-3 UVa 1151 (有边集的最小生成树+二进制枚举子集)
标题指的边集是说这道题的套餐, 是由几条边构成的. 思路是先做一遍最小生成树排除边, 因为如果第一次做没有加入的边, 到后来新加入了很多权值为0的边,这些边肯定排在最前面,然后这条边的前面的那些边肯定 ...
- UVA - 1151 Buy or Build (买还是建)(并查集+二进制枚举子集)
题意:平面上有n个点(1<=n<=1000),你的任务是让所有n个点连通.可以新建边,费用等于两端点欧几里德距离的平方.也可以购买套餐(套餐中的点全部连通).问最小费用. 分析: 1.先将 ...
- 【uva 1151】Buy or Build(图论--最小生成树+二进制枚举状态)
题意:平面上有N个点(1≤N≤1000),若要新建边,费用是2点的欧几里德距离的平方.另外还有Q个套餐,每个套餐里的点互相联通,总费用为Ci.问让所有N个点连通的最小费用.(2组数据的输出之间要求有换 ...
- Good Bye 2015B(模拟或者二进制枚举)
B. New Year and Old Property time limit per test 2 seconds memory limit per test 256 megabytes input ...
- HDU 5025Saving Tang Monk BFS + 二进制枚举状态
3A的题目,第一次TLE,是因为一次BFS起点到终点状态太多爆掉了时间. 第二次WA,是因为没有枚举蛇的状态. 解体思路: 因为蛇的数目是小于5只的,那就首先枚举是否杀死每只蛇即可. 然后多次BFS, ...
- UVA1354-Mobile Computing(二进制枚举子集)
Problem UVA1354-Mobile Computing Accept:267 Submit:2232 Time Limit: 3000 mSec Problem Description ...
随机推荐
- 小P的故事——神奇的换零钱&&人活着系列之平方数
http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2777&cid=1219 这题不会,看了别人的代码 #include <iostre ...
- df值自由度学习[转载]
转自:https://www.applysquare.com/topic-cn/78TAnIzZ6/ https://zhidao.baidu.com/question/175605082855699 ...
- openstack 部署笔记--neutron控制节点
控制节点 配置neutron用户及服务 $ . admin-openrc $ openstack user create --domain default --password-prompt neut ...
-  
这个东西在 html 里是空格占位符,普通的空格在 html 里如果连续的多个可能被认为只有一个,而这个东西你写几个就能占几个空格位.
- 为什么size_t重要?
参见 http://en.cppreference.com/w/cpp/types/size_t size_t其实与uintptr_t一个道理.就是一个东西.指针其实就是寻址,与地址总线位数一致,编译 ...
- mysql buffer
php与mysql的连接有三种方式,mysql,mysqli,pdo.不管使用哪种方式进行连接,都有使用buffer和不使用buffer的区别. 什么叫使用buffer和不使用buffer呢? 客户端 ...
- MySQL实现SQL Server排名函数
最近在MySQL中遇到分组排序查询时,突然发现MySQL中没有row_number() over(partition by colname)这样的分组排序.并且由于MySQL中没有类似于SQL Ser ...
- iOS 绘图 (UIImage的一些操作)
UIGraphicsBeginImageContextWithOptions,本文主要在图片类型上下文中对图片进行操作,具体实现的功能: - 1.生成图片 - 2.绘制图片到视图 - 3.添加水印 ...
- Solr安装中文分词器IK
安装环境 jdk1.7 solr-4.10.3.tgz KAnalyzer2012FF_u1.jar tomcat7 VM虚拟机redhat6.5-x64:192.168.1.201 Xshell4 ...
- python print 使用分隔符 或行尾符
使用print() 函数输出数据,但是想改变默认的分隔符或者行尾符. >>> print('ACME', 50, 91.5) ACME 50 91.5 >>> pr ...