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

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

思路:

  有重边,要用邻接表。所给的每条边都要变成4条有向边!否则可能一开始就到达不了终点了。最后要再加上一个源点和汇点,容量cap(源点,1)=2,指定只能走两次,再规定其他所给的边的容量是1就行了,当边被走过了,就自动增加了流,也就走不了了。

  解释看代码更清晰。

  1 //#pragma comment(linker,"/STACK:102400000,102400000")
  2 #include <iostream>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <vector>
  6 #include <stack>
  7 #include <algorithm>
  8 #include <map>
  9 //#include <bits/stdc++.h>
 10 #define LL long long
 11 #define pii pair<int,int>
 12 #define INF 0x7f7f7f7f
 13 using namespace std;
 14 const int N=10000+5;
 15 vector<int> vect[N];
 16 struct node
 17 {
 18     int from;
 19     int to;
 20     int cost;
 21     int cap;
 22     int flow;
 23 }edge[N*4];     //边数是4*M的大小
 24
 25 int edge_num;   //边的上限
 26 int f[N];       //流
 27 int path[N];    //记录路径
 28 int c[N];       //记录费用
 29 bool in[N];     //是否在queue中
 30
 31 void add_node(int a, int b, int c, int ca, int fl)
 32 {
 33     edge[edge_num].from=a;
 34     edge[edge_num].to=b;
 35     edge[edge_num].cost=c;
 36     edge[edge_num].cap=ca;
 37     edge[edge_num].flow=fl;
 38     vect[a].push_back(edge_num++);
 39 }
 40
 41
 42 LL spfa(int s,int e)
 43 {
 44     deque<int> que;
 45     que.push_back(s);
 46     c[s]=0;
 47     f[s]=INF;
 48     in[s]=1;
 49     while(!que.empty())
 50     {
 51         int x=que.front();
 52         que.pop_front();
 53         in[x]=0;
 54         for(int i=0; i<vect[x].size(); i++)
 55         {
 56             node t=edge[vect[x][i]];
 57             if(t.cap>t.flow && c[t.to]>c[t.from]+t.cost)  //能流过,且费用更小即可更新。
 58             {
 59                 path[t.to]=vect[x][i];          //记边号,方便更新flow
 60                 c[t.to]=c[t.from]+t.cost;       //更新cost,相当于距离
 61                 f[t.to]=min(f[t.from], t.cap-t.flow);
 62                 if(!in[t.to])
 63                 {
 64                     que.push_back(t.to);
 65                     in[t.to]=1;
 66                 }
 67             }
 68         }
 69     }
 70     return c[e];
 71 }
 72
 73 int m;
 74
 75 int mcmf(int s, int e)
 76 {
 77     LL ans=0;
 78     while(1)
 79     {
 80         memset(f, 0, sizeof(f));
 81         memset(c, 0x7f, sizeof(c));
 82         memset(in, 0, sizeof(in));
 83         memset(path, 0, sizeof(path));
 84
 85         int tmp=spfa(s, e);
 86         if(tmp==INF)    return ans;
 87         ans+=tmp*f[e];   //这是最小费用。注:每次的流可能不是1。
 88
 89         int ed=e;
 90         while(ed!=s)
 91         {
 92             int en=path[ed];
 93             edge[en].flow+=f[e];
 94             edge[en^1].flow-=f[e];
 95             ed=edge[en].from;
 96             //cout<<edge[en].from<<"-"<<edge[en].to<<endl;
 97         }
 98     }
 99 }
100
101
102
103
104
105 int main()
106 {
107     freopen("input.txt", "r", stdin);
108     int  n, a, b, c;
109     while(~scanf("%d%d", &n, &m))
110     {
111         for(int i=n*2; i>=0; i--)   vect[i].clear();
112         edge_num=0;
113         for(int i=0; i<m; i++)
114         {
115             scanf("%d%d%d",&a,&b,&c);
116             add_node(a,b,c,1,0);    //4条有向边。
117             add_node(b,a,-c,0,0);
118
119             add_node(b,a,c,1,0);
120             add_node(a,b,-c,0,0);
121         }
122         add_node(0,1,0,2,0);        //加多2条边
123         add_node(1,0,0,0,0);        //加这条无意义,但是更新flow时更方便
124         add_node(n,n+1,0,2,0);
125         add_node(n+1,n,0,0,0);
126
127         printf("%lld\n",mcmf(0, n+1));
128     }
129
130
131     return 0;
132 }

AC代码

时间: 2024-10-27 05:37:30

POJ 2135 Farm Tour(最小费用最大流,变形)的相关文章

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

题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很难,因为要保证每条边只能走一次,那么我们把边拆为两个点,一个起点和终点,容量是1,权重是这条路的长度.然后两个端点分别向起点连接容量是1权重是0的边,终点分别向两个端点连容量是1权重是0的边,从源点到1连容量为2权重为0的边,从n到汇点连容量为2权重为0的边. #include<stdio.h>

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

Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18150   Accepted: 7023 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

poj 2135 Farm Tour 最小费最大流

inf开太小错了好久--下次还是要用0x7fffffff #include<stdio.h> #include<string.h> #include<vector> #include<queue> #include<algorithm> using namespace std; const int N=5024; const int inf=0x7fffffff; struct Edge { int from,to,cap,flow,cost;

poj 2135 Farm Tour (最小费用最大流模板)

网络流的费用: 在实际应用中,与网络流有关的问题,不仅涉及流量,而且还有费用的因素.网络的每一条边(v,w)除了给定容量cap(v,w)外,还定义了一个单位流量费用cost(v,w) 最小费用最大流问题 给定网络G,要求G的一个最大用流flow,使流的总费用最小. 求解MCMF问题的算法: 最小费用最大流最常用和基本的算法我们可以称它为最小费用路算法,其思想与求最大流的增广路算法类似,不断在残流网络中寻找从源s到汇t的最小费用路,即残流网络中从s到t的以费用为权的最短路,然后沿最小费用路增流,直

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

题目:poj 2135 Farm Tour 题意:给出一个无向图,问从 1 点到 n 点然后又回到一点总共的最短路. 分析:这个题目不读仔细的话可能会当做最短路来做,最短路求出来的不一定是最优的,他是两条分别最短,但不一定是和最短. 我们可以用费用流来很轻易的解决,建边容量为1,费用为边权,然后源点s连 1 ,费用0 ,容量 2 ,n点连接汇点,容量2,费用0,,就可以了. 注意这个题目是无向图,所以要建双向边. AC代码: #include <iostream> #include <a

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

POJ 2135 Farm Tour(费用流)

POJ 2135 Farm Tour 题目链接 题意:给定一个无向图,边有权值,求从1到n再从n到1的最短路 思路:费用流,连边容量为1(注意是无向图),然后源点和1连容量2,n和汇点连容量是2 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; const int

POJ 2135 Farm Tour (dinic算法,网络流)

构图方法: 注意题目中的边为无向边.新建源点s 和 汇点t 每两条道路连一条容量为1,费用为w的边.s到1连一条容量为1,费用为0 的边,n到 t 连一条容量为1,费用为0 的边,求最大流. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <queue> #include

POJ 2195 Going Home (最小费用最大流)

题目链接:http://poj.org/problem?id=2195 题意:n*m的矩阵,地图上有若干个人(m)和房子(H),且人与房子的数量一致.man每移动一格费用为1,一个房子只能住一个人.现在要求所有的人出发,都入住房子,求最少话费. 思路:建立一个超级源点和汇点,源点与人相连费用为0,容量为1,人与房子相连,费用为人与房子的距离,容量为1,房子与汇点相连,费用为0,容量为1 #include <iostream> #include <cstdlib> #include

POJ 2516 Minimum Cost(最小费用最大流,坑题)

题目链接:http://poj.org/problem?id=2516 题意:有N个店,M个供货商,K种商品.已知供货商的仓库里每种商品的数量以及每种商品运送到每个店的费用,每个店铺对各种商品的需求数量,求最少话费. Input  第一行:N,M,K. 然后1 - N行,每行 K列 ,第I行第J个数代表 第I个店铺 需要第J种物品多少件. 然后 N+1 - M行  ,每行 K列 , 第I行第J个数代表 第I个供货商 有第J种物品多少件. 然后是K个矩阵  ,每个N行M列,第ji个矩阵的第i行第j