CodeForces 21D Traveling Graph 状压dp+欧拉回路

题目链接:点击打开链接

题意:

给定n个点m条边的无向图

求从1点开始经过每条边至少一次最后回到1点的最小路程

显然就是找一条路径可重复的欧拉回路

思路:

首先对于欧拉回路的结论是:所有点的度数都为偶数

因为所有边至少经过一次,那么可以把题意转换成加最少多少条边使得图满足以上结论

而加的边目的是为了把奇度数转成偶度数,先floyd一下得到任意点间加边的最小花费

dp[i]表示状态i下度数都为偶数的最小花费。

状压dp,把i状态下,所有未选择的点中挑2个奇度数的转移即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#include <set>
#include <math.h>
using namespace std;
#define ll int
#define inf 1000000007
#define N 16
int dis[N][N], n, m;
void floyd(){
	for(ll k = 0; k < n; k++)
		for(ll i = 0; i < n; i++)
			for(ll j = 0; j < n; j++)
				dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j]);
	for(ll i = 0; i < n; i++)dis[i][i] = 0;
}
int du[N], ans, dp[1<<N];//dp[i] 表示加边使得i状态下的所有点都是偶度数的最小花费
ll work(){
	ll i, j, k;
	for(i = 1; i < n; i++)//如果i这个点有边连接,但点0又走不到这个点,说明和这个点相连的边是走不到的,即图不连通
		if(du[i] && dis[0][i]==inf)return -1;

	ll all = (1<<n)-1;
	for(i = 0; i <= all; i++)	dp[i] = inf;
	dp[0] = 0;
	for(k = 0; k <= all; k++)
	{
		for(i = 0; i < n; i++)//找到一个奇度数的点i
			if((du[i]&1) && (k&(1<<i)))break;
		if(i==n)dp[k] = 0;
		for(i = 0; i < n; i++)// 枚举奇数度点i
			if((du[i]&1) && !(k&(1<<i)))
				for(j = i+1; j < n; j++)// 枚举奇数度点j
					if((du[j]&1) && !(k&(1<<j)) && dis[i][j]<inf)
						dp[k|(1<<i)|(1<<j)] = min(dp[k|(1<<i)|(1<<j)],dp[k]+dis[i][j]);
	}
	if(dp[all]>=inf)return -1;
	return ans + dp[all];
}
int main(){
	ll i, j, u, v, w;
	while(cin>>n>>m){
		for(i=0;i<n;i++)for(j=0;j<n;j++)dis[i][j] = inf;
		memset(du, 0, sizeof du);
		ans = 0;
		while(m--){
			cin>>u>>v>>w; u--; v--;
			dis[u][v] = dis[v][u] = min(dis[u][v], w);
			du[u]++; du[v]++;
			ans += w;
		}
		floyd();
		cout<<work()<<endl;
	}
	return 0;
}

CodeForces 21D Traveling Graph 状压dp+欧拉回路,布布扣,bubuko.com

时间: 2024-08-05 11:15:00

CodeForces 21D Traveling Graph 状压dp+欧拉回路的相关文章

Codeforces 580D-Kefa and Dishes(状压DP)

原题链接:http://codeforces.com/problemset/problem/580/D 题意:在n个数字中有顺序地选择m个数字,每个数字对应有个值ai,每取一个数字答案加上ai,并且存在k个关系:x y c,如果x恰好排在y的前面,那么答案再加上ci的值.输出最大值. 思路:状压dp.dp[i][j]中,i是已经选了若干个数的情况,j是最后一个被选取的数,i从选取1个到m个枚举下去,j从第1个数到第n个数进行枚举就能得到答案. AC代码: 1 #include<iostream>

COdeforces#417D Cunning Gena(状压DP)

A boy named Gena really wants to get to the "Russian Code Cup" finals, or at least get a t-shirt. But the offered problems are too complex, so he made an arrangement with his n friends that they will solve the problems for him. The participants

Codeforces 544E Remembering Strings 状压dp

题目链接 题意: 给定n个长度均为m的字符串 下面n行给出字符串 下面n*m的矩阵表示把对应的字母修改成其他字母的花费. 问: 对于一个字符串,若它是easy to remembering 当 它存在一个字母,使得这个字母在这一列是独一无二的. 要使得n个字符串都是easy to remembering 的最小花费. 第一个样例是把第一列的4个a中3个a修改成别的字母,所以花费为3. 思路: 显然是个状压dp,但需要一点转化. 首先得到一个结论: 对于某一列,设这一列的字母是 a,a,b,b,a

CodeForces 327E Axis Walking(状压DP+卡常技巧)

Iahub wants to meet his girlfriend Iahubina. They both live in Ox axis (the horizontal axis). Iahub lives at point 0 and Iahubina at point d. Iahub has n positive integers a1, a2, ..., an. The sum of those numbers is d. Suppose p1, p2, ..., pn is a p

Codeforces 327E Axis Walking (状压dp lowbit优化)

E. Axis Walking time limit per test:3 seconds memory limit per test:512 megabytes Iahub wants to meet his girlfriend Iahubina. They both live in Ox axis (the horizontal axis). Iahub lives at point 0 and Iahubina at point d. Iahub has n positive integ

CodeForces 907E Party(bfs+状压DP)

Arseny likes to organize parties and invite people to it. However, not only friends come to his parties, but friends of his friends, friends of friends of his friends and so on. That's why some of Arseny's guests can be unknown to him. He decided to

Codeforces 327E Axis Walking 状压dp(水

题目链接:点击打开链接 题意: 给定n个数,随意排列. 给定k个违禁数b[]. 问:有多少个排列使得这个排列的 n项前缀和中不出现违禁数. (formally,if it's a legal permutation, sum[i] != b[j] (1<=i<=n, 1<=j<=k)) sum[0] = 0; sum[i] = sum[i-1]+a[permutaion[i]]; ==java党表示被tle,心疼自己T^T #include <stdio.h> cons

Codeforces Gym 100676G Training Camp 状压dp

http://codeforces.com/gym/100676 题目大意是告诉你要修n门课,每门课有一个权值w[i], 在第k天修该课程讲获得k*w[i]的学习点数,给出了课程与先修课程的关系,要修该课程必须修完先修课程.问最多能学到多少点数. 非常简单的一道状压dp(一开始我还误导队友写成两维的去了 T^T); dp[s] : s 的二进制存放的是已经选择的课程,在该状态下的能获得的最大的点数. 这时如果再学一门课程k,将转移到状态ss (s | (1 << k) ) ,能否转移需要判断合

CodeForces 757D Felicity&#39;s Big Secret Revealed(状压DP)

题意:给定一个01串,一个有效的n切割定义如下:一个横杠代表一次切割,第一条横杠前面的01串不算,最后一条横杠后面的01串不算,将两个横杠中的01串转化成十进制数字,假设这些数字的最大值是MAX且这些数字囊括了1-MAX的所有数字,则称为一次有效切割.求2~n+1次有效切割的切法. 思路: 由于题目要求包含所有1-MAXN的数字,且n<=75,所以MAXN<=20.另dp[i][j]表示第i位前面有一个横杆且存在j这个状态,接着从第i位开始枚举到第j位为下一个横杆的位置,设这两段横杆之间的数字