uva 818(dfs+图+状态压缩)

题意:有n个环,编号从1到n,给出了一些环环相扣的情况,比如给a和b表示a和b两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链。

题解:状态压缩把所有的打开环的情况枚举出来,然后拿去判断是否成立,更新打开环后的图g[i][j],和每个点的度数,不成立有三种情况,1.计算没有打开的环的度数,如果大于2说明不会有链,2.把没有打开环拿去dfs,访问过就vis[i]++,如果vis[i]>=2说明存在环,3.如果打开的环数num + 1小于链的数量,说明无法连成一个链。找到最小值输出。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 20;
int vis[N], n, deg[N], g[N][N];

void dfs(int u, int fa) {
	for (int i = 0; i < n; i++) {
		if (g[u][i] && i != fa) {
			vis[i]++;
			if (vis[i] < 2)
				dfs(i, u);
		}
	}
}

bool solve(int s, int num) {
	memset(deg, 0, sizeof(deg));
	memset(vis, 0, sizeof(vis));
	int link = 0;
	for (int i = 0; i < n; i++) {
		if (s & (1 << i)) {
			for (int j = 0; j < n; j++) {
				if (g[i][j])
					g[i][j] = g[j][i] = 0;
			}
		}
	}
	for (int i = 0; i < n; i++) {
		if (!(s & (1 << i))) {
			for (int j = 0; j < n; j++)
				if (g[i][j])
					deg[i]++;
			if (deg[i] > 2)
				return false;
		}
	}
	for (int i = 0; i < n; i++) {
		if (!(s & (1 << i)) && !vis[i]) {
			link++;
			vis[i]++;
			dfs(i, -1);
		}
	}
	for (int i = 0; i < n; i++)
		if (vis[i] >= 2)
			return false;
	if (link > num + 1)
		return false;
	return true;
}

int main() {
	int f[N][N], cas = 1, a, b;
	while (scanf("%d", &n) == 1 && n) {
		memset(f, 0, sizeof(f));
		while (scanf("%d%d", &a, &b) && a != -1) {
			f[a - 1][b - 1] = 1;
			f[b - 1][a - 1] = 1;
		}
		int res = 0x3f3f, tt = 1 << n;
		for (int i = 0; i < tt; i++) {
			for (int j = 0; j < n; j++)
				for (int k = 0; k < n; k++)
					g[j][k] = f[j][k];
			int temp = 0;
			for (int j = 0; j < n; j++)
				if (i & (1 << j))
					temp++;
			if (solve(i, temp))
				res = min(res, temp);
		}
		printf("Set %d: Minimum links to open is %d\n", cas++, res);
	}
	return 0;
}
时间: 2024-10-13 07:13:39

uva 818(dfs+图+状态压缩)的相关文章

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就

codeforces B - Preparing Olympiad(dfs或者状态压缩枚举)

B. Preparing Olympiad You have n problems. You have estimated the difficulty of the i-th one as integer ci. Now you want to prepare a problemset for a contest, using some of the problems you've made. A problemset for the contest must consist of at le

UVA 11008--Antimatter Ray Clearcutting+状态压缩记忆化搜索

题目链接:点击进入 最多只有16个点,如果不用状态压缩的话,最优子结构没法找到.所以我们进行状态压缩,用一个数表示当前的状态,对应二进制位为1表示该位置的树还未被砍掉,为0表示已被砍掉,初始状态为(1< #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 20 #define INF 0x3f3f3f3f typedef struct { i

uva658(最短路径+隐式图+状态压缩)

题目连接(vj):https://vjudge.net/problem/UVA-658 题意:补丁在修正 bug 时,有时也会引入新的 bug.假定有 n(n≤20)个潜在 bug 和 m(m≤100) 个补丁,每个补丁用两个长度为 n 的字符串表示,其中字符串的每个位置表示一个 bug.第一 个串表示打补丁之前的状态("-" 表示该 bug 必须不存在,"+" 表示必须存在,0 表示无所 谓),第二个串表示打补丁之后的状态("-" 表示不存在,

UVA 11464 - Even Parity 状态压缩,分析 难度: 2

题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2459 题意 N*N 的01方阵,可用操作为把任意0变为1,求操作的最小次数,使得任意位置的上下左右之和(不包含自身)为偶数 思路 如刘书,关键在于状态只有第一行的2^15个. 感想 1. 忘了memset 代码 #include <algorithm> #include

UVA 1252-Twenty Questions(状态压缩DP+子集枚举)

题目大意:有n个物品,每个物品有m个特征,每个物品的每个特征都可能有或没有,现在假定某个物品,通过询问某些特征来确定这个物品,问最多需要多少次就可以确定物品. 每次询问之后可能根据答案不同来采取不同的进一步询问的策略. 用d[S][S0]表示目前询问了S,得到的回答是S0(即那个物品在S中有S0这些特征),最少还需询问多少次.枚举下一次询问的特征完成递推.最终d[0][0]就是答案.S0显然是S的一个子集.下一次询问的特征不是S已有的特征.如果对于某个d[S][S0]只有一个物品满足,那么此时值

UVA 1633-Dyslexic Gollum(状态压缩DP)

题目大意:求长度为N(1<=N<=400)且不含长度大于或等于K(1<=K<=10)的回文串的01串. 用d[i][j][u]表示长度为i且后11个01串组成数j且不含长度大于或等于u的01串有多少个. 如果j中含有长度至少为u的回文串,那么d[i][j][u]=0. 否则,假设d[i][j][u]可以由d[i-1][v][u]转移得来.根据状态的表示,那么v的低10位肯定是u的高10位,v的最高一位可以为0或1,即v=j/2或v=j/2+(1<<10). 程序将表打出

UVA 11825 - Hackers&amp;#39; Crackdown 状态压缩 dp 枚举子集

UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共同拥有n种服务,每台计算机上都执行着所有服务,对于每台计算机,你能够选择停止一项服务,这个行为会导致与这台计算机和与他相连的其它计算机上的这项服务都停止(原来已经停止的继续保持停止状态). 求最多能使多少个服务瘫痪(即没有不论什么一台计算机在执行这项服务). 分析: 题目说白了.就

hdu 5067 网络赛 状态压缩 或dfs

题意是给你n*m的方格 里面有最多10个格子有数  问你最少走多少步能将所有的数字移到左上角    能无限装下数字 这里介绍两种做法  dfs和状态压缩dp 1   dfs 由于每个数字之间是一定可以到达的  所有只用考虑走有数字的情况   最多10!种情况  找到做小的就行   果断的深搜       注意下优化 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; s