Tour

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)

Total Submission(s): 2299    Accepted Submission(s): 1151

Problem Description
In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one-way roads connecting them. You are lucky enough to have a chance to have a tour in the kingdom. The route should be designed as: The route should contain one or more loops.
(A loop is a route like: A->B->……->P->A.)

Every city should be just in one route.

A loop should have at least two cities. In one route, each city should be visited just once. (The only exception is that the first and the last city should be the same and this city is visited twice.)

The total distance the N roads you have chosen should be minimized.
 
Input
An integer T in the first line indicates the number of the test cases.

In each test case, the first line contains two integers N and M, indicating the number of the cities and the one-way roads. Then M lines followed, each line has three integers U, V and W (0 < W <= 10000), indicating that there is a road from U to V, with the
distance of W.

It is guaranteed that at least one valid arrangement of the tour is existed.

A blank line is followed after each test case.
 
Output
For each test case, output a line with exactly one integer, which is the minimum total distance.
 
Sample Input
1
6 9
1 2 5
2 3 5
3 1 10
3 4 12
4 1 8
4 6 11
5 4 7
5 6 9
6 5 4
 
Sample Output
42
 

用费用流G++能够卡过,C++会超时。

用KM应该非常快吧,如今先刷费用流,过几天再好好做KM。

题意:给出n个点m条单向边边以及经过每条边的费用,让你求出走过一个哈密顿环(除起点外,每一个点仅仅能走一次)的最小费用。题目保证至少存在一个环满足条件,事实上推断成环仅仅须要推断是否满流就可以。

思路: 把每一个点i拆分成左点i和右点i+N

1。超级源点连左点。容量为1,费用为0

2。全部右点连超级汇点,容量为1。费用为0

3,每条单向边—— 起点左点 连 终点右点 容量为1,费用为边权。

最后跑一下费用流即可了。

注意重边的处理,不去重费用流会超时,还有要用G++提交。  抽出时间再补上KM的AC代码。

费用流AC代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#define MAXN 400+10
#define MAXM 70000+10
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
int from, to, cap, flow, cost, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int pre[MAXN], dist[MAXN];
bool vis[MAXN];
int N, M;
int source, sink;
void init()
{
edgenum = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w, int c)//必须去重!!! {
int i;
for(i = head[u]; i != -1; i = edge[i].next)
{
if(edge[i].to == v)
break;
}
if(i != -1)
{
if(edge[i].cost > c)
edge[i].cost = c, edge[i^1].cost = -c;
return ;
}
Edge E1 = {u, v, w, 0, c, head[u]};
edge[edgenum] = E1;
head[u] = edgenum++;
Edge E2 = {v, u, 0, 0, -c, head[v]};
edge[edgenum] = E2;
head[v] = edgenum++;
}
void getMap()
{
scanf("%d%d", &N, &M);
int a, b, c;
source = 0, sink = 2 * N + 1;
//把每一个点i拆分成左点i和右点i+N
//超级源点连左点。容量为1,费用为0
//全部右点连超级汇点。容量为1,费用为0
//单向边: 起点左点连终点右点 容量为1,费用为边权
for(int i = 1; i <= N; i++)
addEdge(source, i, 1, 0),
//addEdge(i, i + N, 1, 0),
addEdge(i + N, sink, 1, 0);
while(M--)
{
scanf("%d%d%d", &a, &b, &c);
addEdge(a, b+N, 1, c);
}
}
bool SPFA(int s, int t)
{
queue<int> Q;
memset(dist, INF, sizeof(dist));
memset(vis, false, sizeof(vis));
memset(pre, -1, sizeof(pre));
dist[s] = 0;
vis[s] = true;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i].next)
{
Edge E = edge[i];
if(dist[E.to] > dist[u] + E.cost && E.cap > E.flow)
{
dist[E.to] = dist[u] + E.cost;
pre[E.to] = i;
if(!vis[E.to])
{
vis[E.to] = true;
Q.push(E.to);
}
}
}
}
return pre[t] != -1;
}
void MCMF(int s, int t, int &cost, int &flow)
{
flow = cost = 0;
while(SPFA(s, t))
{
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
Edge E = edge[i];
Min = min(Min, E.cap - E.flow);
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
edge[i].flow += Min;
edge[i^1].flow -= Min;
cost += edge[i].cost * Min;
}
flow += Min;
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
init();
getMap();
int cost, flow;
MCMF(source, sink, cost, flow);
printf("%d\n", cost);
}
return 0;
}

KM算法:重刷

边权取负。注意重边的处理。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 210
using namespace std;
int lx[MAXN], ly[MAXN];
int Map[MAXN][MAXN];
bool visx[MAXN], visy[MAXN];
int slack[MAXN];
int match[MAXN];
int N, M;
void getMap()
{
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++)
Map[i][j] = -INF;
}
int a, b, c;
while(M--)
{
scanf("%d%d%d", &a, &b, &c);
if(-c > Map[a][b])
Map[a][b] = -c;
}
}
int DFS(int x)
{
visx[x] = true;
for(int y = 1; y <= N; y++)
{
if(visy[y]) continue;
int t = lx[x] + ly[y] - Map[x][y];
if(t == 0)
{
visy[y] = true;
if(match[y] == -1 || DFS(match[y]))
{
match[y] = x;
return 1;
}
}
else if(slack[y] > t)
slack[y] = t;
}
return 0;
}
void KM()
{
memset(match, -1, sizeof(match));
memset(ly, 0, sizeof(ly));
for(int x = 1; x <= N; x++)
{
lx[x] = -INF;
for(int y = 1; y <= N; y++)
lx[x] = max(lx[x], Map[x][y]);
}
for(int x = 1; x <= N; x++)
{
for(int i = 1; i <= N; i++)
slack[i] = INF;
while(1)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
if(DFS(x)) break;
int d = INF;
for(int i = 1; i <= N; i++)
{
if(!visy[i] && slack[i] < d)
d = slack[i];
}
for(int i = 1; i <= N; i++)
{
if(visx[i])
lx[i] -= d;
}
for(int i = 1; i <= N; i++)
{
if(visy[i])
ly[i] += d;
else
slack[i] -= d;
}
}
}
int ans = 0;
for(int i = 1; i <= N; i++)
ans += Map[match[i]][i];
printf("%d\n", -ans);
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &N, &M);
getMap();
KM();
}
return 0;
}

hdoj 3488 Tour 【最小费用最大流】【KM算法】的更多相关文章

  1. TZOJ 1513 Farm Tour(最小费用最大流)

    描述 When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 &l ...

  2. Farm Tour(最小费用最大流模板)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18150   Accepted: 7023 Descri ...

  3. POJ2135 Farm Tour —— 最小费用最大流

    题目链接:http://poj.org/problem?id=2135 Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  4. poj 2351 Farm Tour (最小费用最大流)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17230   Accepted: 6647 Descri ...

  5. poj 2135 Farm Tour 最小费用最大流建图跑最短路

    题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...

  6. POJ 2135 Farm Tour [最小费用最大流]

    题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很 ...

  7. hdu 1853 Cyclic Tour 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 There are N cities in our country, and M one-way ...

  8. [poj] 1235 Farm Tour || 最小费用最大流

    原题 费用流板子题. 费用流与最大流的区别就是把bfs改为spfa,dfs时把按deep搜索改成按最短路搜索即可 #include<cstdio> #include<queue> ...

  9. POJ-2516(最小费用最大流+MCMF算法)

    Minimum Cost POJ-2516 题意就是有n个商家,有m个供货商,然后有k种商品,题目求的是满足商家的最小花费供货方式. 对于每个种类的商品k,建立一个超级源点和一个超级汇点.每个商家和源 ...

  10. POJ-2195(最小费用最大流+MCMF算法)

    Going Home POJ-2195 这题使用的是最小费用流的模板. 建模的时候我的方法出现错误,导致出现WA,根据网上的建图方法没错. 这里的建图方法是每次到相邻点的最大容量为INF,而花费为1, ...

随机推荐

  1. 通过DOM实现点击隐藏父元素

    HTML代码简单如下: <ul id='ul1'> <li><a href="javascript:">1</a></li&g ...

  2. go package包的使用

    一.标准库 引入 在我们之前所写的所以代码中,我们基本上可以看到fmt这个导入的包,但是我们却不知道如何去写这种包. 如果我们可以自己去写,那么我们就可以将一个功能的集合统一的放入包中,便于以后使用, ...

  3. C++对象的内存模型

    1. 普通对象模型 对象是如何在内存中布局的? 成员 存放位置 访问范围 非静态数据成员 每一个对象体内 为该对象专有 静态数据成员 程序的静态存储区内,只有一份实体 为该类所有对象共享 成员函数(静 ...

  4. YTBro Video 2016-07-30 Sat

    明日天气:多云转阴,32~24度 运动向 健身 20中极致疯狂的俯卧撑,新手请勿尝试 跑酷 大神放大招,招招见血,不信你看 赛事 2016年世界室内田径锦标赛 男子4×400接力决赛 台球 RP集中爆 ...

  5. (转)基于Metronic的Bootstrap开发框架经验总结(6)--对话框及提示框的处理和优化

    http://www.cnblogs.com/wuhuacong/p/4775282.html 在各种Web开发过程中,对话框和提示框的处理是很常见的一种界面处理技术,用得好,可以给用户很好的页面体验 ...

  6. Redis 之string结构及命令详解

    1.set  key  value  ex  秒数   px  毫秒数  nx / xx  设置一个值,注:ex 与 px 同时存在时,取写在后面的一个为有效期,nx表示key不存时设置成功,xx表示 ...

  7. PDF怎么替换页面,教你一招秒实现

    PDF格式是在办公中比较常用的文件格式之一,虽然很好用,也很容易携带,但也容易出现一个问题,当你想要对PDF文件操作或者修改的时候,才发现PDF文件不是那么容易就能进行编辑和修改的,特别是需要对PDF ...

  8. 浏览器内置的base64方法

    Base64是一种基于64个可打印字符来表示二进制数据的表示方法.在Base64中的可打印字符包括字母A-Z.a-z.数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同(维基百科: ...

  9. Robot Framework(六)变量

    变量 2.5.1简介 变量是Robot Framework的一个不可或缺的特性,它们可以在测试数据的大多数地方使用.最常见的是,它们用于测试用例表和关键字表中关键字的参数,但所有设置都允许在其值中使用 ...

  10. Python 文件操作 day2

    一.打开文件的模式1:读.写.追加 1.r读:读模式,只能读,不能写,打开不存在的文件会报错:可省略'r',因为不写默认是读模式 f = open('filename',encoding='utf-8 ...