ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Farm Tour 最小费用流

2019-09-23 21:37:43  阅读:278  来源: 互联网

标签:Farm dis 最小 len int Tour include adj define


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

FJ又来搞事,他这次想在无向图里,从节点1到节点N走一圈,问走着一圈最短的距离是多少。
首先呢,先说一下为什么不能两次最短路求解。
在这里插入图片描述对于这个图,大家可以试着自己跑一下最短路和最小费用流。
如果对于一个有向图,那么在找去程和回程的路径时,选择的边不相重复,也就是说这两个过程相互独立,是可以用最短路单独计算去程和回程的最短路并相加的。
但是对于一个无向图,在寻找去程和回程的路径时,是从同一个边集中挑选边,也就是说这两个过程相互关联,无法一次贪心得到结果,所以采用最小费用流模型求解。

最后是关于无向图建边的问题。如果每条边只能用一次的话,是不能正反建两次的,因为这样建边会导致这条边在算法中用过两次;如果没有限制,就正反建两次,只要不超出内存限制的话。
那么有限制的话要真么处理呢?首先看一下这条无向边初始情况,开始时,这条边即可以正向走,也可以反向走
在这里插入图片描述
但是一旦选定了一个方向走,比如从A到B,那么这个方向就不能在选用,而且被选择方向的反方向(B到A)变成负权边,用于表示退流
在这里插入图片描述综上,在建边的时候,初始化正向和反向容量都是1,之后则与普通的最小费用流无异。
如果这样的话,考虑上图退流之后边的状态。
在这里插入图片描述我们惊奇的发现,无法表示从B到A这条路径了,那这样是不是代表这样建边是错的呢?
那不然不是。我们可以想一下,在退流之后这条边端点的状态。在退流之后,这两个端点都被连上另一条新的边,而且 连上新的边所形成的路径 要比之前 使用这条边形成的路径 的权值要小,也就是说,这条边不会再被使用了,所以他能不能表示正确的状态已经无所谓了。


#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>

#define MAXN 1005
#define LIM 3500000000
#define starNode 0
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return

#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define getLen(name,index) name[index].size()
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
struct Edge{
    int to,cap,rev,len;
};

int N,M;
ll dis[MAXN];
int Vpre[MAXN],Epre[MAXN];
vector<Edge> adj[MAXN];
inline void addEdge(int star,int finish,int cap,int len);
int minCost(int star,int finish,int f);
int main(){
    ios::sync_with_stdio(false);

    while(cin>>N>>M){
        rep(i,0,M){
            int commonA,commonB,len;
            cin>>commonA>>commonB>>len;
            addEdge(commonA,commonB,1,len);
        }
        adj[starNode].push_back((Edge){1,2,getLen(adj,1),0});
        adj[starNode].push_back((Edge){starNode,0,getLen(adj,starNode)-1,0});

        cout<<minCost(starNode,N,2)<<endl;

        rep(i,0,N+1)
            adj[i].clear();
    }

    re 0;
}
inline void addEdge(int star,int finish,int cap,int len){
    adj[star].push_back((Edge{finish,cap,getLen(adj,finish),len}));
    adj[finish].push_back((Edge){star,cap,getLen(adj,star)-1,len});
}
int minCost(int star,int finish,int f){
    int sum=0;

    while(f>0){
        rep(i,0,N+1)
            dis[i]=LIM;
        dis[1]=0;
        bool update=true;
        while(update){
            update=false;
            rep(i,1,N+1){
                if(dis[i]==LIM)
                    continue;
                rep(j,0,getLen(adj,i)){
                    Edge &e=adj[i][j];
                    if(e.cap>0 && dis[e.to]>dis[i]+e.len){
                        dis[e.to]=dis[i]+e.len;
                        Vpre[e.to]=i;
                        Epre[e.to]=j;
                        update=true;
                    }
                }

            }
        }
        if(dis[finish]==LIM){
            cout<<"need to finish"<<endl;
            re -1;
        }

        for(int v=finish;v!=star;v=Vpre[v]){
            Edge &e=adj[Vpre[v]][Epre[v]];

            sum+=e.len;
            e.cap=0;
            e.len*=(-1);
            adj[e.to][e.rev].cap=1;
            adj[e.to][e.rev].len*=(-1);
        }

        f--;
    }
    return sum;
}

标签:Farm,dis,最小,len,int,Tour,include,adj,define
来源: https://blog.csdn.net/white_156/article/details/88819926

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有