Chinese Postman Problem Aizu - DPL_2_B(无向图中国邮路问题)
题意:
带权无向图上的中国邮路问题:一名邮递员需要经过每条边至少一次,最后回到出发点,一条边多次经过权值要累加,问最小总权值是多少。(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(无向图中国邮路问题)的更多相关文章
- The Chinese Postman Problem HIT - 2739(有向图中国邮路问题)
无向图的问题,如果每个点的度数为偶数,则就是欧拉回路,而对于一个点只有两种情况,奇数和偶数,那么就把都为奇数的一对点 连一条 边权为原图中这两点最短路的值 的边 是不是就好了 无向图中国邮路问 ...
- HITOJ 2739 The Chinese Postman Problem(欧拉回路+最小费用流)
The Chinese Postman Problem My Tags (Edit) Source : bin3 Time limit : 1 sec Memory limit : 6 ...
- 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 ...
- HIT2739 The Chinese Postman Problem(最小费用最大流)
题目大概说给一张有向图,要从0点出发返回0点且每条边至少都要走过一次,求走的最短路程. 经典的CPP问题,解法就是加边构造出欧拉回路,一个有向图存在欧拉回路的充分必要条件是基图连通且所有点入度等于出度 ...
- 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 ...
- Problem E: 穷游中国在统题 优先队列 + 模拟
http://www.gdutcode.sinaapp.com/problem.php?cid=1049&pid=4 Problem E: 穷游中国在统题 Description Travel ...
- LightOJ1086 Jogging Trails(欧拉回路+中国邮递员问题+SPFA)
题目求从某点出发回到该点经过所有边至少一次的最短行程. 这个问题我在<图论算法理论.实现及应用>中看过,是一个经典的问题——中国邮递员问题(CPP, chinese postman pro ...
- Soj题目分类
-----------------------------最优化问题------------------------------------- ----------------------常规动态规划 ...
- 贪心算法:旅行商问题(TSP)
TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出.问题描述如下: 有若干个城市,任何两个城市之间 ...
随机推荐
- HDMI传输原理:TMDS
参考资料:http://blog.sina.com.cn/s/blog_679686370100vgg1.html: http://www.eeworld.com.cn/mndz/2011/0818/ ...
- (原创)odoo在docker环境下无法备份
odoo容器内置postgresql-client版本和数据库版本不一致,安装和数据库版本相同或者更高版本的客户端 参考:https://www.postgresql.org/download/lin ...
- 【转】Oracle中的decode在mysql中的等价实现
以前用的Oracle,里面的Decode函数非常好用,那MySql实现同样的功能用什么呢?——MySql使用if的语法来支持. 格式:IF(expr1,expr2,expr3)如果expr1是TRUE ...
- QZEZ第一届“饭吉圆”杯程序设计竞赛
终于到了饭吉圆杯的开赛,这是EZ我参与的历史上第一场ACM赛制的题目然而没有罚时 不过题目很好,举办地也很成功,为法老点赞!!! 这次和翰爷,吴骏达 dalao,陈乐扬dalao组的队,因为我们有二个 ...
- 《Head First 设计模式》例子的C++实现(2 观察者模式)
最近在学习设计模式,用的是 <Head First 设计模式>这本书.感觉这本书写的还是很不错的,深入浅出的介绍了各种常用的设计模式.唯一有点不方便的地方是这本书的例子全都是用的 Java ...
- 【JVM.2】垃圾收集器与内存分配策略
垃圾收集器需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 在前一节中介绍了java内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈 ...
- Visual Studio2017 数据库架构比较
一.前言 开发的时候在测试服务器上和线网服务器上面都有我们的数据库,当我们在线网上面修改或者新增一些字段后,线网的数据库也需要更新,这个时候根据表的修改记录,然后在线网上面一个一个增加修改很浪费效率而 ...
- 个人项目Week1
一.项目时间规划与实际用时 PSP2.1 Personal Software Process Stages 预计时间/h 实际时间/h Planning 计划 · Estimate · 估计这 ...
- Linux内核分析 笔记六 进程的描述和进程的创建 ——by王玥
一.知识点总结 (一)进程的描述 1.操作系统内核里有三大功能: 进程管理 内存管理 文件系统 2.进程描述符:task_struct 2.进程描述符——struct task_struct 1. p ...
- 使用代理创建连接池 proxyPool
配置文件properties url=jdbc:mysql://127.0.0.1:3306/mine?characterEncoding=UTF-8 user=root password=1234 ...