POJ 2135 Farm Tour (网络流,最小费用最大流)

Description

When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= N <= 1000) fields numbered 1..N, the first of which contains his house and the Nth of which contains the big barn. A total M (1 <= M <= 10000) paths that connect the fields in various ways. Each path connects two different fields and has a nonzero length smaller than 35,000.

To show off his farm in the best way, he walks a tour that starts at his house, potentially travels through some fields, and ends at the barn. Later, he returns (potentially through some fields) back to his house again.

He wants his tour to be as short as possible, however he doesn't want to walk on any given path more than once. Calculate the shortest tour possible. FJ is sure that some tour exists for any given farm.

Input

Line 1: Two space-separated integers: N and M.

Lines 2..M+1: Three space-separated integers that define a path: The starting field, the end field, and the path's length.

Output

A single line containing the length of the shortest tour.

Sample Input

4 5

1 2 1

2 3 1

3 4 1

1 3 2

2 4 2

Sample Output

6

Http

POJ:https://vjudge.net/problem/POJ-2135

Source

图论,网络流,最小费用最大流

题目大意

给定一个n个点m条边的无向图,求两条不相交的从1到n的最短路径。

解决思路

看到这道题目时,首先想到的是最短路径的算法,但显然不是跑两边Dijkstra或spfa,想要两条路一起走也不科学,所以我们想到了网络流算法。

想一想,我们要求两条不相交的从1到n的最短路径,若假设我们把所有的边看作流量为1的边,那么这是不是要求从1到n容量为2的流呢?所以我们可以想到有如下的算法:

对于原来的边上的权值“距离”,我们将其换一个定义:花费。另外再给每一个边赋上1的流量。同时,为了控制1点流出的和n点汇入的流不超过2,我们再设一个超级源点和超级汇点,在超级源点与1之间连流量为2的边,而在n与超级汇点之间连流量为2的边。然后,我们就可以用最小费用最大流来解决了。

需要注意的是,这道题目的边是无向边,所以我们在网络流连边时也要连无向边,所以本题不能用邻接矩阵来存图,而要使用邻接表的形式

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std; const int maxN=5001;
const int maxM=50001;
const int inf=2147483647; class Edge
{
public:
int u,v,flow,cost;//记录每一条边的信息,出点,目的点,残量,花费
}; int n,m;
int cnt=-1;//记录邻接表的边数
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int Flow[maxN];//spfa中保存每个点可以通过的残量
int Pre[maxN];//spfa中保存每个点是由哪一条边转移过来的边的标号
int Dist[maxN];//spfa中保存到每个点的距离,即最小花费
bool inqueue[maxN]; void Add_Edge(int u,int v,int flow,int cost);//添加边
void _Add(int u,int v,int flow,int cost);
bool spfa(); int main()
{
cin>>n>>m;
memset(Head,-1,sizeof(Head));
memset(Next,-1,sizeof(Next));
for (int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Add_Edge(u,v,1,w);//注意,正反边都要连
Add_Edge(v,u,1,w);
}
Add_Edge(0,1,2,0);//连接源点与1
Add_Edge(n,n+1,2,0);//连接n与汇点
int Ans=0;//记录花费
while (spfa())//spfa寻增广路
{
int now=n+1;
int last=Pre[now];//从汇点向回走,将增广路上的每一条边均减去消耗的流量
while (now!=0)
{
E[last].flow-=Flow[n+1];
E[last^1].flow+=Flow[n+1];
now=E[last].u;
last=Pre[now];
}
Ans+=Dist[n+1]*Flow[n+1];//累计花费
}
cout<<Ans<<endl;
} void Add_Edge(int u,int v,int flow,int cost)
{
_Add(u,v,flow,cost);//每一次加边的同时,加入其反向边,反向边的残量为0,花费为-cost
_Add(v,u,0,-cost);
return;
} void _Add(int u,int v,int flow,int cost)
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
E[cnt].u=u;
E[cnt].v=v;
E[cnt].flow=flow;
E[cnt].cost=cost;
return;
} bool spfa()
{
memset(Pre,-1,sizeof(Pre));//前驱边的编号
memset(inqueue,0,sizeof(inqueue));
memset(Flow,0,sizeof(Flow));
memset(Dist,127,sizeof(Dist));
queue<int> Q;
while (!Q.empty())
Q.pop();
Q.push(0);//将源点放入队列
Dist[0]=0;
Flow[0]=inf;
inqueue[0]=1;
do
{
int u=Q.front();
//cout<<u<<endl;
inqueue[u]=0;
Q.pop();
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].flow>0)&&(Dist[u]+E[i].cost<Dist[v]))//当还有残量存在且花费更小时,修改v的信息
{
Dist[v]=E[i].cost+Dist[u];
Pre[v]=i;
Flow[v]=min(Flow[u],E[i].flow);
if (inqueue[v]==0)
{
Q.push(v);
inqueue[v]=1;
}
}
}
}
while (!Q.empty());
if (Pre[n+1]==-1)//当汇点没有前驱,及说明没有增广到汇点,也说明不存在增广路,直接退出
return 0;
return 1;
}

POJ 2135 Farm Tour (网络流,最小费用最大流)的更多相关文章

  1. POJ 2135 Farm Tour (最小费用最大流模板)

    题目大意: 给你一个n个农场,有m条道路,起点是1号农场,终点是n号农场,现在要求从1走到n,再从n走到1,要求不走重复路径,求最短路径长度. 算法讨论: 最小费用最大流.我们可以这样建模:既然要求不 ...

  2. POJ 2135 Farm Tour(最小费用最大流)

    Description When FJ's friends visit him on the farm, he likes to show them around. His farm comprise ...

  3. POJ 2135 Farm Tour(最小费用最大流,变形)

    题意:给一个无向图,FJ要从1号点出发到达n号点,再返回到1号点,但是路一旦走过了就会销毁(即回去不能经过),每条路长度不同,那么完成这趟旅行要走多长的路?(注:会有重边,点号无序,无向图!) 思路: ...

  4. poj 2135 Farm Tour【 最小费用最大流 】

    第一道费用流的题目--- 其实---还是不是很懂,只知道沿着最短路找增广路 建图 源点到1连一条容量为2(因为要来回),费用为0的边 n到汇点连一条容量为2,费用为0的边 另外的就是题目中输入的了 另 ...

  5. Minimum Cost 【POJ - 2516】【网络流最小费用最大流】

    题目链接 题意: 有N个商家它们需要货物源,还有M个货物供应商,N个商家需要K种物品,每种物品都有对应的需求量,M个商家每种物品都是对应的存货,然后再是K个N*M的矩阵表示了K个物品从供货商运送到商家 ...

  6. POJ2135 Farm Tour(最小费用最大流)

    题目问的是从1到n再回到1边不重复走的最短路,本质是找1到n的两条路径不重复的尽量短的路. #include<cstdio> #include<cstring> #includ ...

  7. poj 2135 Farm Tour 【无向图最小费用最大流】

    题目:id=2135" target="_blank">poj 2135 Farm Tour 题意:给出一个无向图,问从 1 点到 n 点然后又回到一点总共的最短路 ...

  8. 网络流(最小费用最大流):POJ 2135 Farm Tour

    Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: ...

  9. POJ 2135.Farm Tour 消负圈法最小费用最大流

    Evacuation Plan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4914   Accepted: 1284   ...

随机推荐

  1. Android开发——JobScheduler机制

    年Google开发大会上指出,如果每个APP都使用这个API,那么可以节约15%到20%的电量. 2.  JobScheduler拥有更多的触发选项 JobScheduler比AlarmManager ...

  2. VS新建一个模板工程

    新建一个模板工程的好处:    1.就不用每次都走一边新建向导了,新建工程一步到位. 2.可以往项目中每次都的输入的代码,如一些声明注释-- 效果图: 具体步骤: 1.自己先新建一个属于自己的工程. ...

  3. python高并发和多线程的关系

    “高并发和多线程”总是被一起提起,给人感觉两者好像相等,实则 高并发 ≠ 多线程 多线程是完成任务的一种方法,高并发是系统运行的一种状态,通过多线程有助于系统承受高并发状态的实现.   高并发是一种系 ...

  4. OLEDB 命令转换组件的用法

    在数据流任务组件中,OLEDB 命令转换组件对输入的每行数据调用TSQL,该组件能够把输入的数据作为参数,因此,该转换组件主要用于运行参数化的查询. 命令转换组件的配置十分简单,只有三个可编辑属性,位 ...

  5. Reflux系列01:异步操作经验小结

    写在前面 在实际项目中,应用往往充斥着大量的异步操作,如ajax请求,定时器等.一旦应用涉及异步操作,代码便会变得复杂起来.在flux体系中,让人困惑的往往有几点: 异步操作应该在actions还是s ...

  6. 【转】浅谈php://filter的妙用

    php://filter是PHP中独有的协议,利用这个协议可以创造很多“妙用”,本文说几个有意思的点,剩下的大家自己下去体会. XXE中的使用 php://filter之前最常出镜的地方是XXE.由于 ...

  7. Arcengine效率探究之一——属性的读取(转载)

    http://blog.csdn.net/lk103852503/article/details/6566652 在写一个对属性表的统计函数时,发现执行速度奇慢无比,百思不得其解,其实算法并不复杂,后 ...

  8. linux使用curl上传文件并且同时携带其它传递参数

    一般使用linux原生态的命令curl上传文件时命令如下 假如要上传文件是myfile.txt curl -F "file_name=@myfile.txt" -X POST &q ...

  9. 20135202闫佳歆--week4 两种方式使用同一个系统调用--实验及总结

    实验四 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 在这里我选择的是第20号系统调用,getpid. 1.使用库函数API: 代码如下: /* getpid.c */ #incl ...

  10. 【MOOC EXP】Linux内核分析实验三报告

     程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 [跟踪分析Linux内核的启动过程] ...