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&ndash;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 ...
随机推荐
-
『.NET Core CLI工具文档』(十二)dotnet-pack
说明:本文是个人翻译文章,由于个人水平有限,有不对的地方请大家帮忙更正. 原文:dotnet-pack 翻译:dotnet-pack 名称 dotnet-pack - 将代码打包成 NuGet 包 概 ...
-
从AdventureWorks学习数据库建模——实体分析
最近打算写写数据库建模的文章,所以打算分析微软官方提供的SQL Server示例数据库AdventureWorks,看看这个数据库中有哪些值得学习的地方. 首先我们需要下载安装一个SQL Server ...
-
转mysql存储引擎memory,ndb,innodb之选择
1 mysql的innodb和cluster的NDB引擎都支持事务,在有共同的特性外,也有不同之处:以mysql cluster NDB 7.3和MySQL 5.6之InnoDB为例:ndb7.3基于 ...
-
ZooKeeper -- 分布式开源协调服务
ZooKeeper是一个为分布式应用所设计的开源协调服务,适用于大型的分布式系统,可以提供统一命名服务.状态同步服务.集群管理.分布式应用配置项的管理等服务.ZooKeeper支持Java和C两种编程 ...
-
jemalloc源码结构分析(一):内存申请处理过程
一.5种malloc方法 1)tcache_alloc_small 2)arena_malloc_small 3)tcache_alloc_large 4)arena_malloc_large 5)h ...
-
vs默认的app.config是哪个?
一:这次是进一步的三层构架,不过还是没有业务逻辑层,但有单独的层的文件夹,解决方案资源管理器图如下: 二:operatorDAl.cs代码: using System; using System.Co ...
-
C++中实现 time_t, tm 相互转换
time_t -> tm: localtime tm -> time_t: mktime time_t curTime; time(&curTime); dwCurTime = c ...
-
java-concurrent包
通常所说的concurrent包基本有3个package组成 java.util.concurrent:提供大部分关于并发的接口和类,如BlockingQueue,Callable,Concurren ...
-
C++中string、char *、char[]的转换
头段时间有人问过我这个问题,可是我一点头绪都没有,直接说不会.现在从网上找了点资料,看了看,知道点东西了. 一.string转char*. 主要有三种方法可以将str转换为char*类型,分别是:da ...
-
linux搭建node环境
这篇完全够了! 地址:https://www.cnblogs.com/lovefc/p/8847343.html 附上一张图: