hdu 3488(KM算法||最小费用最大流)
Tour
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2925 Accepted Submission(s): 1407
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.
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.
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
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = ;
const int N = ;
const int M = ;
struct Edge{
int u,v,cap,cost,next;
}edge[M];
int head[N],tot,low[N],pre[N];
int total ;
bool vis[N];
int flag[N][N];
void addEdge(int u,int v,int cap,int cost,int &k){
edge[k].u=u,edge[k].v=v,edge[k].cap = cap,edge[k].cost = cost,edge[k].next = head[u],head[u] = k++;
edge[k].u=v,edge[k].v=u,edge[k].cap = ,edge[k].cost = -cost,edge[k].next = head[v],head[v] = k++;
}
void init(){
memset(head,-,sizeof(head));
tot = ;
}
bool spfa(int s,int t,int n){
memset(vis,false,sizeof(vis));
for(int i=;i<=n;i++){
low[i] = (i==s)?:INF;
pre[i] = -;
}
queue<int> q;
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for(int k=head[u];k!=-;k=edge[k].next){
int v = edge[k].v;
if(edge[k].cap>&&low[v]>low[u]+edge[k].cost){
low[v] = low[u] + edge[k].cost;
pre[v] = k; ///v为终点对应的边
if(!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t]==-) return false;
return true;
}
int MCMF(int s,int t,int n){
int mincost = ,minflow,flow=;
while(spfa(s,t,n))
{
minflow=INF+;
for(int i=pre[t];i!=-;i=pre[edge[i].u])
minflow=min(minflow,edge[i].cap);
flow+=minflow;
for(int i=pre[t];i!=-;i=pre[edge[i].u])
{
edge[i].cap-=minflow;
edge[i^].cap+=minflow;
}
mincost+=low[t]*minflow;
}
total=flow;
return mincost;
}
int n,m;
int main(){
int tcase;
scanf("%d",&tcase);
while(tcase--){
init();
scanf("%d%d",&n,&m);
int src = ,des = *n+;
for(int i=;i<=n;i++){
addEdge(src,i,,,tot);
addEdge(i+n,des,,,tot);
}
memset(flag,-,sizeof(flag));
for(int i=;i<=m;i++){ ///去重
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(flag[u][v]==-||w<flag[u][v]){
flag[u][v] = w;
}
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(flag[i][j]!=-){
addEdge(i,j+n,,flag[i][j],tot);
}
}
}
int mincost = MCMF(src,des,*n+);
if(total!=n) printf("-1\n");
else printf("%d\n",mincost);
}
}
题解二:KM算法,也是将一个点看成两个点,算最优匹配即可.
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = ;
const int N = ;
int graph[N][N];
int lx[N],ly[N];
int linker[N];
bool x[N],y[N];
int n,m;
void init(){
memset(lx,,sizeof(lx));
memset(ly,,sizeof(ly));
memset(linker,-,sizeof(linker));
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(lx[i]<graph[i][j]) lx[i] = graph[i][j];
}
}
}
bool dfs(int u){
x[u] = true;
for(int i=;i<=n;i++){
if(!y[i]&&graph[u][i]==lx[u]+ly[i]){
y[i] = true;
if(linker[i]==-||dfs(linker[i])){
linker[i] = u;
return true;
}
}
}
return false;
}
int KM(){
int sum = ;
init();
for(int i=;i<=n;i++){
while(){
memset(x,false,sizeof(x));
memset(y,false,sizeof(y));
if(dfs(i)) break;
int d = INF;
for(int j=;j<=n;j++){
if(x[j]){
for(int k=;k<=n;k++){
if(!y[k]) d = min(d,lx[j]+ly[k]-graph[j][k]);
}
}
}
if(d==INF) break;
for(int j=;j<=n;j++){
if(x[j]) lx[j]-=d;
if(y[j]) ly[j]+=d;
}
}
}
for(int i=;i<=n;i++){
sum+=graph[linker[i]][i];
}
return sum;
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
graph[i][j] = -INF;
}
}
for(int i=;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
graph[u][v] = max(graph[u][v],-w);
}
int ans = KM();
printf("%d\n",-ans);
}
return ;
}
不去重之后还可以很快跑过去的某大牛的模板.
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<climits>
#include<assert.h>
#include<functional>
using namespace std;
const int maxn=;
const int INF=;
typedef pair<int,int> P; struct edge
{
int to,cap,cost,rev;
edge(int t,int c,int co,int r)
:to(t),cap(c),cost(co),rev(r){}
edge(){}
}; int V;//the number of points
vector<edge>G[maxn];
int h[maxn];
int dist[maxn];
int prevv[maxn],preve[maxn];
void add_edge(int from,int to,int cap,int cost)
{
G[from].push_back(edge(to,cap,cost,G[to].size()));
G[to].push_back(edge(from,,-cost,G[from].size()-));
} void clear()
{
for(int i=;i<V;i++) G[i].clear();
} int min_cost_flow(int s,int t,int f)
{
int res=,k=f;
fill(h,h+V,);//如果下标从1开始,就要+1
while(f>)
{
priority_queue<P,vector<P>,greater<P> >que;
fill(dist,dist+V,INF);
dist[s]=;
que.push(P(,s));
while(!que.empty())
{
P cur=que.top();que.pop();
int v=cur.second;
if(dist[v]<cur.first) continue;
for(int i=;i<G[v].size();i++)
{
edge &e=G[v][i];
if(e.cap>&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to])
{
dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
prevv[e.to]=v;
preve[e.to]=i;
que.push(P(dist[e.to],e.to));
}
}
}
if(dist[t]==INF)
{
return -;
}
for(int v=;v<V;v++) h[v]+=dist[v];//从0还是1开始需要结合题目下标从什么开始 int d=f;
for(int v=t;v!=s;v=prevv[v])
{
d=min(d,G[prevv[v]][preve[v]].cap);
}
f-=d;
res+=d*h[t];
for(int v=t;v!=s;v=prevv[v])
{
edge &e=G[prevv[v]][preve[v]];
e.cap-=d;
G[v][e.rev].cap+=d;
}
}
return res;
} int n,m;
int main(){
int tcase;
scanf("%d",&tcase);
while(tcase--){
scanf("%d%d",&n,&m);
clear();
V=*n+;
int src = ,des = *n+;
for(int i=;i<=n;i++){
add_edge(src,i,,);
add_edge(i+n,des,,);
}
for(int i=;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,n+v,,w);
}
int mincost = min_cost_flow(src,des,n);
printf("%d\n",mincost);
}
}
hdu 3488(KM算法||最小费用最大流)的更多相关文章
- hdu 3395(KM算法||最小费用最大流(第二种超级巧妙))
Special Fish Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- hdu 1533 Going Home 最小费用最大流
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533 On a grid map there are n little men and n house ...
- HDU 5988.Coding Contest 最小费用最大流
Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- hdu 3667(拆边+最小费用最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3667 思路:由于花费的计算方法是a*x*x,因此必须拆边,使得最小费用流模板可用,即变成a*x的形式. ...
- HDU–5988-Coding Contest(最小费用最大流变形)
Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- POJ 2195 & HDU 1533 Going Home(最小费用最大流)
这就是一道最小费用最大流问题 最大流就体现到每一个'm'都能找到一个'H',但是要在这个基础上面加一个费用,按照题意费用就是(横坐标之差的绝对值加上纵坐标之差的绝对值) 然后最小费用最大流模板就是再用 ...
- hdu 1533 Going Home 最小费用最大流 入门题
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- hdoj 3488 Tour 【最小费用最大流】【KM算法】
Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submi ...
随机推荐
- Delight for a Cat
Time Limit: 1000 ms Memory Limit: 512 MB Description 从前,有一只懒猫叫CJB.每个小时,这只猫要么在睡觉,要么在吃东西,但不能一边睡觉一边吃东 ...
- 单例 ------ JAVA实现
单例:只能实例化一个对象,使用场景比如打印机. 最推荐的是采用饿汉式:双重校验锁用到了大量的语法,不能保证这些语法在所用场合一定没问题,所以不是很推荐:总之简单的才是最好的,就饿汉式!!! C++ 创 ...
- [freemarker篇]06.超级强大的自定义指令
Freemarker的自定义指令是很强大的,非常强大,在之后的教程中我会简单的做一个示例,让大家对其有所了解!如果做Freemarker编程,请好好看看API手册,可以说里面的内容很多!也是一门独立的 ...
- JavaScript的性能优化:加载和执行
随着 Web2.0 技术的不断推广,越来越多的应用使用 javascript 技术在客户端进行处理,从而使 JavaScript 在浏览器中的性能成为开发者所面临的最重要的可用性问题.而这个问题又因 ...
- java mysql 连接
第一种: //驱动程序名 String driver = "com.mysql.jdbc.Driver"; //URL指向要访问的数据库名mydata String url = & ...
- 通过eclipse mybatis generater代码生成插件自动生成代码
Mybatis属于半自动ORM,在使用这个框架中,工作量最大的就是书写Mapping的映射文件,由于手动书写很容易出错,我们可以利用Mybatis-Generator来帮我们自动生成文件.通过在Ecl ...
- UVA 1635 Irrelevant Elements
https://vjudge.net/problem/UVA-1635 题意:n个数,每相邻两个求和,最后变成1个数,问这个数除m的余数与第几个数无关 n个数使用次数分别为C(n-1,i) i∈[0, ...
- MyBatis框架的使用及源码分析(十二) ParameterHandler
在StatementHandler使用prepare()方法后,接下来就是使用ParameterHandler来设置参数,让我们看看它的定义: package org.apache.ibatis.ex ...
- 前端表单序列化为json串,以及构造json数组、json串
var parm={ username:"zhangsan", age:24, email:"352400260@qq.com" }; console.log( ...
- py_faster_rcnn识别出来的结果好多红框重叠
py_faster_rcnn识别出来的结果好多红框重叠, 可以通过调节demo.py中的NMS_THRESH的值进行限制. NMS_THRESH表示非极大值抑制,这个值越小表示要求的红框重叠度越小,0 ...