题意:

  带权无向图上的中国邮路问题:一名邮递员需要经过每条边至少一次,最后回到出发点,一条边多次经过权值要累加,问最小总权值是多少。(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. JavaWeb学习总结-12 JSTL标签语言

    一 JSTL JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签. 除了 ...

  2. CSS3选择器之:nth-child(n)

    第一次用到这个选择器还是为了解决下面了的问题: 手机的前端,我们使用了mint-ui,里面有一个日期选择控件,但是选择的时候没有提供年月的选择器,如: 而是提供了下面的方式: 为了达到上面的效果,使用 ...

  3. C# webApi上传图片 代码篇

    十年河东,十年河西,莫欺少年穷 学无止境,精益求精 代码篇,不多说 如下: using System; using System.Collections.Generic; using System.D ...

  4. 【强化学习】python 实现 saras lambda 例一

    本文作者:hhh5460 本文地址:https://www.cnblogs.com/hhh5460/p/10147265.html 将例一用saras lambda算法重新撸了一遍,没有参照任何其他人 ...

  5. 总目录(Catalog)

    总目录(Catalog) C#高级编程(C# advanced programming) 1.并发编程(Concurrent programming)(8) ...... 数据结构与算法(Data s ...

  6. FreeRTOS 任务与调度器(1)

    前言: Task.c和Task.h文件内是FreeRTOS的核心内容,所有任务和调度器相关的API函数都在这个文件中,它包括下图这些内容FreeRTOS文件如下: Task.c和Task.h文件内是F ...

  7. Linux配置mail客户端发送邮件

    1. 概述 在Linux操作系统环境中,可以配置邮件服务器,也可以配置邮箱客户端.本篇主要是配置邮件客户端,这对于发送服务器一些系统信息十分有必要. 2. mail客户端安装 2.1 安装mailx ...

  8. 【nodejs】让nodejs像后端mvc框架(asp.net mvc )一样处理请求--路由限制及选择篇(2/8)【route】

    文章目录 前情概要 上文中的RouteHandler中有一个重要方法GetActionDescriptor没有贴代码和说,接下来我们就说一说这个方法. 使用controllerName.actionN ...

  9. 开发CMDB系统

    背景: 在现网环境中服务器多了每天服务器的配置 情况我们很难记住,当某台服务器硬件配置变化后可以第一时间了解,某台服务器出现问题时可以快速定位机架位置,之前都是excel文档,要查某项数据时极不方便. ...

  10. php 中self,this的区别和实地操作

    面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行PHP的高级编程,对于提高PHP编程能力和规划web开发构架都是很有意 ...