HITOJ 2739 The Chinese Postman Problem(欧拉回路+最小费用流)
The Chinese Postman Problem
My Tags | (Edit) |
---|
Source : bin3 | |||
Time limit : 1 sec | Memory limit : 64 M |
Submitted : 503, Accepted : 172
A Chinese postman is assigned to a small town in China to deliver letters. In this town, each street is oriented and connects exactly two junctions. The postman's task is to start at the post office and pass each street at least once to deliver letters. At last, he must return to the post office.
Can you help him to make sure whether there exist feasible routes for him and find the minimum distance from all the feasible routes.
Input
Input contains multiple test cases. The first line is an integer T, the number of test cases. Each case begins with two integers N, M, with 2 ≤ N ≤ 100, 1 ≤ M ≤ 2000, representing the number of junctions and the number of streets respectively.
Then M lines will follow, each denoting a street. A street is represented by three integers u, v, d, with 0 ≤ u, v < N, 0 < d ≤ 1000, meaning this street whose length is d connects the junction u and v and the postman can only travel from junction u to v. Junctions are numbered from 0 to N-1. Junction 0 is always the post office. Note that there may be more than one street connecting the same pair of junctions.
Output
Output one line for each test case. If there exist feasible routes for the postman, output the minimum distance. Otherwise, output -1.
Sample Input
3
2 1
0 1 3
4 4
0 1 1
1 2 2
2 3 3
3 0 4
4 7
0 1 1
1 2 2
2 3 3
3 0 4
1 3 5
3 1 2
1 3 2
Sample Output
-1
10
21
题目链接:HIT 2739
题意就是用最少的费用把所有边跑一边,并最终回到源点,这个跟欧拉回路有一点关系,有向图欧拉回路的充要条件就是所有点的出度和入度相等,并且基图要连通,这题的边方向已经是不能改的了,因此只能通过重复走来使得到达另一些重边,即多走几遍一些边,把某些点的出度和入度补成一样的,那么可以统计所有点的入度和出度之差记为$deg_i=in_i-out_i$,如果一个点$deg_i>0$,说明这个点的入度比较大,需要补充一些,因此要和源点连边;若$deg_i<0$即入度较大,则和汇点连边,这样一来就就可以构图使得流量从入度多的点流向出度多的点,平衡了入度和出度。
代码:
#include <stdio.h>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 110;
const int M = 2010;
struct edge
{
int to, nxt, cap, cost;
edge() {}
edge(int _to, int _nxt, int _cap, int _cost): to(_to), nxt(_nxt), cap(_cap), cost(_cost) {}
} E[(M + N) << 1];
int head[N], tot;
int d[N], pre[N], pat[N], mc, mf;
bitset<N>vis;
int n, m, deg[N]; void init()
{
CLR(head, -1);
tot = 0;
mc = mf = 0;
CLR(deg, 0);
}
inline void add(int s, int t, int cap, int cost)
{
E[tot] = edge(t, head[s], cap, cost);
head[s] = tot++;
E[tot] = edge(s, head[t], 0, -cost);
head[t] = tot++;
}
int spfa(int s, int t)
{
queue<int>Q;
Q.push(s);
CLR(d, INF);
vis.reset();
vis[s] = 1;
d[s] = 0;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = 0;
for (int i = head[u]; ~i; i = E[i].nxt)
{
int v = E[i].to;
if (d[v] > d[u] + E[i].cost && E[i].cap > 0)
{
d[v] = d[u] + E[i].cost;
pre[v] = u;
pat[v] = i;
if (!vis[v])
{
vis[v] = 1;
Q.push(v);
}
}
}
}
return d[t] != INF;
}
void MCMF(int s, int t)
{
int i;
while (spfa(s, t))
{
int df = INF;
for (i = t; i != s; i = pre[i])
df = min(df, E[pat[i]].cap);
for (i = t; i != s; i = pre[i])
{
E[pat[i]].cap -= df;
E[pat[i] ^ 1].cap += df;
}
mf += df;
mc += df * d[t];
}
}
namespace DSU
{
int pre[N], num;
void init()
{
CLR(pre, -1);
num = n;
}
int Find(int n)
{
return pre[n] == -1 ? n : pre[n] = Find(pre[n]);
}
void Merge(int a, int b)
{
int fa = Find(a), fb = Find(b);
if (fa == fb)
return ;
pre[fb] = fa;
--num;
}
int isconnect()
{
return num == 1;
}
}
int main(void)
{
int T, a, b, w, i;
scanf("%d", &T);
while (T--)
{
init();
scanf("%d%d", &n, &m);
DSU::init();
int ori = 0;
for (i = 0; i < m; ++i)
{
scanf("%d%d%d", &a, &b, &w);
DSU::Merge(a, b);
add(a, b, INF, w);
ori += w;
--deg[a];
++deg[b];
}
if (!DSU::isconnect())
puts("-1");
else
{
int S = n, T = n + 1;
int sf = 0;
for (i = 0; i < n; ++i)
{
if (deg[i] > 0)
add(S, i, deg[i], 0);
else if (deg[i] < 0)
{
add(i, T, -deg[i], 0);
sf -= deg[i];
}
}
MCMF(S, T);
printf("%d\n", mf == sf ? mc + ori : -1);
}
}
return 0;
}
HITOJ 2739 The Chinese Postman Problem(欧拉回路+最小费用流)的更多相关文章
- 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 ...
- The Chinese Postman Problem HIT - 2739(有向图中国邮路问题)
无向图的问题,如果每个点的度数为偶数,则就是欧拉回路,而对于一个点只有两种情况,奇数和偶数,那么就把都为奇数的一对点 连一条 边权为原图中这两点最短路的值 的边 是不是就好了 无向图中国邮路问 ...
- HIT2739 The Chinese Postman Problem(最小费用最大流)
题目大概说给一张有向图,要从0点出发返回0点且每条边至少都要走过一次,求走的最短路程. 经典的CPP问题,解法就是加边构造出欧拉回路,一个有向图存在欧拉回路的充分必要条件是基图连通且所有点入度等于出度 ...
- Chinese Postman Problem Aizu - DPL_2_B(无向图中国邮路问题)
题意: 带权无向图上的中国邮路问题:一名邮递员需要经过每条边至少一次,最后回到出发点,一条边多次经过权值要累加,问最小总权值是多少.(2 <= N <= 15, 1 <= M < ...
- 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 ...
- bzoj 1515 [POI2006]Lis-The Postman 有向图欧拉回路
LINK:Lis-The Postman 看完题觉得 虽然容易发现是有向图欧拉回路 但是觉得很难解决这个问题. 先分析一下有向图的欧拉回路:充要条件 图中每个点的入度-出度=0且整张图是一个强连通分量 ...
- Soj题目分类
-----------------------------最优化问题------------------------------------- ----------------------常规动态规划 ...
- LightOJ1086 Jogging Trails(欧拉回路+中国邮递员问题+SPFA)
题目求从某点出发回到该点经过所有边至少一次的最短行程. 这个问题我在<图论算法理论.实现及应用>中看过,是一个经典的问题——中国邮递员问题(CPP, chinese postman pro ...
- 贪心算法:旅行商问题(TSP)
TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出.问题描述如下: 有若干个城市,任何两个城市之间 ...
随机推荐
- ios数据持久化--CoreData框架的介绍和使用
1.Core Data 是数据持久化存储的最佳方式 2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型 在Mac OS X 10.5Leopard及以后的版本中 ...
- Objection, 一个轻量级的Objective-C依赖注入框架
简介 项目主页:https://github.com/atomicobject/objection 实例下载: https://github.com/ios122/ios122 Objection 是 ...
- 关于 export default 和 export
// 第一组 export default function crc32() { // 输出 // ... } import crc32 from 'crc32'; // 输入 // 第二组 expo ...
- npm run build根据不同参数打包不同环境url
config文件夹下 dev.env.js中修改代码 'use strict' const merge = require('webpack-merge') const prodEnv = requi ...
- vue笔记v-if
如果ite.type=='培训',显示第一个img, 如果ite.type=='会议',显示第二个img
- 最短路径之迪杰斯特拉算法(Java)
1)Dijkstra算法适用于求图中两节点之间最短路径 2)Dijkstra算法设计比较巧妙的是:在求源节点到终结点自底向上的过程中,源节点到某一节点之间最短路径的确定上(这也是我之前苦于没有解决的地 ...
- 2、spring boot 配置文件
配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoot自 ...
- 【文件处理】xml 文件 SAX解析
SAX的全称是Simple APIs for XML,也即XML简单应用程序接口. 与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式. 当使用SAX分析器对XML文档 ...
- 12 Django组件-forms组件
forms组件 校验字段功能 针对一个实例:注册用户讲解. 模型:models.py class UserInfo(models.Model): name=models.CharField(max_l ...
- MySQL之查询性能优化(一)
为什么查询速度会慢 通常来说,查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端.其中“执行”可以认为是整个生命周期中最重要的阶段, ...