题意:

  带权无向图上的中国邮路问题:一名邮递员需要经过每条边至少一次,最后回到出发点,一条边多次经过权值要累加,问最小总权值是多少。(2 <= N <= 15, 1 <= M <= 1000)

解析:

  每条边都要至少经过一次, 如果每条边只能经过一次,那么是不是就是一个欧拉回路的问题,但无向图的欧拉回路必须保证 每个点的度数为偶数

所以如果有某个点的度数为奇数,那就比较尴尬了。。。

  因为一条边有两个端点, 所以如果有奇数点,那么奇数点的个数一定是个偶数

  我们先假设在这个无向图中有两个奇点分别为s 和 t,那么根据欧拉路径 s 一定可以经过所有边一次 然后到t , 但我们还要回去,那么是不是走t 到 s 的最短路就好了

那么最短路算法求出这个原图中是t - s的最短路  添加到原图中,是不是就是一个欧拉回路!

  同理 如果奇点个数大于2 ,那么我们就建一个二分图,把这些点分别放到左边 和 右边,每两个点的边权为它们之间的最短路,求最小权匹配就好了

  然后把求出来的这些匹配 添加到原图中  求欧拉回路

  但这题的n比较小  用状压去枚举所有的情况  dp一下就好了

1 如果是连通图,转2,否则返回无解并结束;

2 检查中的奇点,构成图的顶点集;

3 求出中每对奇点之间的最短路径长度,作为图对应顶点间的边权;

4 对进行最小权匹配;

5 把最小权匹配里的每一条匹配边代表的路径,加入到图中得到图;

6 在中求欧拉回路,即所求的最优路线。

 

#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = , INF = 0x7fffffff;
int head[maxn], d[maxn], vis[maxn], deg[maxn], dp[ << + ];
int n, m, cnt;
vector<int> odd;
int way[][];
struct node
{
int u, v, w, next;
}Node[maxn]; void add_(int u, int v, int w)
{
Node[cnt].u = u;
Node[cnt].v = v;
Node[cnt].w = w;
Node[cnt].next = head[u];
head[u] = cnt++;
} void add(int u, int v, int w)
{
add_(u, v, w);
add_(v, u, w);
} int spfa(int s, int t)
{
for(int i = ; i < maxn; i++) d[i] = INF;
queue<int> Q;
mem(vis, );
Q.push(s);
vis[s] = ;
d[s] = ;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
vis[u] = ;
for(int i = head[u]; i != -; i = Node[i].next)
{
node e = Node[i];
if(d[e.v] > d[u] + e.w)
{
d[e.v] = d[u] + e.w;
if(!vis[e.v])
{
Q.push(e.v);
vis[e.v] = ;
}
}
}
}
// cout << s << " " << t << endl;
// cout << d[t] << endl;
return d[t];
} void init()
{
mem(head, -);
mem(way, -);
cnt = ;
} int main()
{
init();
int edge_sum = ;
int u, v, w;
cin >> n >> m;
for(int i = ; i < m; i++)
{
cin >> u >> v >> w;
add(u, v, w);
deg[u]++;
deg[v]++;
// way[u][v] = way[v][u] = w;
edge_sum += w;
}
for(int i = ; i < n; i++) if(deg[i] & ) odd.push_back(i); //n的数比较小 所以用状压dp枚举所有情况 即可
int len = odd.size();
for(int i = ; i < ( << len); i++) dp[i] = INF;
dp[] = ;
for(int mask = ; mask < ( << len); mask++)
{
int ncnt = __builtin_popcount(mask); //统计mask中有多少个1
if(ncnt & ) continue;
vector<int> bits; //bits[i]代表了mask第bits[i]位有1 同时也是odd里的第bits[i]个数的下标
for(int i = ; i < len; i++)
if(mask & ( << i)) bits.push_back(i);
// int blen = bits.size();
for(int i = ; i < ncnt - ; i++)
{
for(int j = i + ; j < ncnt; j++)
{
int sp_mask = mask ^ ( << bits[i]) ^ ( << bits[j]);
int u = odd[bits[i]], v = odd[bits[j]];
int shost_path = way[u][v] == - ? spfa(u, v) : way[u][v];
way[u][v] = way[v][u] = shost_path;
dp[mask] = min(dp[mask], dp[sp_mask] + shost_path);
}
}
} cout << edge_sum + dp[( << len) - ] << endl; return ;
}

Chinese Postman Problem Aizu - DPL_2_B(无向图中国邮路问题)的更多相关文章

  1. The Chinese Postman Problem HIT - 2739(有向图中国邮路问题)

    无向图的问题,如果每个点的度数为偶数,则就是欧拉回路,而对于一个点只有两种情况,奇数和偶数,那么就把都为奇数的一对点  连一条  边权为原图中这两点最短路的值  的边  是不是就好了 无向图中国邮路问 ...

  2. HITOJ 2739 The Chinese Postman Problem(欧拉回路+最小费用流)

    The Chinese Postman Problem My Tags   (Edit)   Source : bin3   Time limit : 1 sec   Memory limit : 6 ...

  3. HIT 2739 - The Chinese Postman Problem - [带权有向图上的中国邮路问题][最小费用最大流]

    题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2739 Time limit : 1 sec Memory limit : 64 M A Chinese ...

  4. HIT2739 The Chinese Postman Problem(最小费用最大流)

    题目大概说给一张有向图,要从0点出发返回0点且每条边至少都要走过一次,求走的最短路程. 经典的CPP问题,解法就是加边构造出欧拉回路,一个有向图存在欧拉回路的充分必要条件是基图连通且所有点入度等于出度 ...

  5. FZU - 2038 -E - Another Postman Problem (思维+递归+回溯)

    Chinese Postman Problem is a very famous hard problem in graph theory. The problem is to find a shor ...

  6. Problem E: 穷游中国在统题 优先队列 + 模拟

    http://www.gdutcode.sinaapp.com/problem.php?cid=1049&pid=4 Problem E: 穷游中国在统题 Description Travel ...

  7. LightOJ1086 Jogging Trails(欧拉回路+中国邮递员问题+SPFA)

    题目求从某点出发回到该点经过所有边至少一次的最短行程. 这个问题我在<图论算法理论.实现及应用>中看过,是一个经典的问题——中国邮递员问题(CPP, chinese postman pro ...

  8. Soj题目分类

    -----------------------------最优化问题------------------------------------- ----------------------常规动态规划 ...

  9. 贪心算法:旅行商问题(TSP)

    TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出.问题描述如下: 有若干个城市,任何两个城市之间 ...

随机推荐

  1. MIPI接口资料汇总(精)

    一.介绍 1.MIPI联盟,即移动产业处理器接口(Mobile Industry Processor Interface 简称MIPI)联盟.MIPI(移动产业处理器接口)是MIPI联盟发起的为移动应 ...

  2. 使用Quartz实现定时任务

    一:Quertz的用途 Quertz是一个开源的作业任务调度框架,他可以完成像JavaScript定时器类式的功能,其实Java中Timer也可实现部分功能,但相比Quertz还是略逊一筹,本人这次需 ...

  3. React-state props与render()的关系

    state或者props发生改变,render()j就会执行一次. 父组件的render()被重新执行时,它的子组件的render()都会重新执行.

  4. 算法相关——Java排序算法之桶排序(一)

    (代码中对应一个数组的下标),将每个元素放入对应桶中,再将所有元素按顺序输出(代码中则按顺序将数组i下标输出arrary[i]次),即为{0,1,3,5,5,6,9}. 1.2  代码实现 /* *@ ...

  5. 浅淡volatile原理

    Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性” Volatile的官方定义 Java语言规范第三版中对volatile的定义如下: java编程语言允 ...

  6. 在平衡树的海洋中畅游(四)——FHQ Treap

    Preface 关于那些比较基础的平衡树我想我之前已经介绍的已经挺多了. 但是像Treap,Splay这样的旋转平衡树码亮太大,而像替罪羊树这样的重量平衡树却没有什么实际意义. 然而类似于SBT,AV ...

  7. BugkuCTF web基础$_GET

    前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...

  8. linux下日志文件error监控报警脚本分享

    即对日志文件中的error进行监控,当日志文件中出现error关键字时,即可报警!(grep -i error 不区分大小写进行搜索"error"关键字,但是会将包含error大小 ...

  9. Maven 项目生成或者update jdk变为1.5的问题

    在使用Maven构建项目时,生成的maven项目jdk默认使用的是jdk1.5. 在手动修改了jdk之后,update project之后jdk又会变为1.5. 或者用eclipse的Maven插件生 ...

  10. restfull环境搭建-helloword(二)

    原文地址:http://only81.iteye.com/blog/1689537 本文描述,获取XML或json格式数据 首先,创建一个bean,比如Todo(JAXB自动将bean文件,转换成xm ...