poj2135(最小费用最大流入门)

Farm Tour
Time Limit: 1000MS

Memory Limit: 65536K
Total Submissions: 18976

Accepted: 7334
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
    Source

网络流学习推荐博客:https://blog.csdn.net/txl199106/article/details/64441994

这道题详解在https://blog.csdn.net/u012171516/article/details/49431065,这个流的构图是真的难,这只是个简单的构图
注意: * 本质上是求从1~n的流量为2的最小费用流
# 不能直接用两次dijkstra来求。(将第一次走过的路删掉再跑第二次)
研究问题模型的时候别被题意牵着走,要看出本质的模型

转自:https://blog.csdn.net/u012171516/article/details/49431065
这题可以转换成网络流的费用流。
来回并且路径不相同就相当于有用两条从1到N的路径。
把路径长度当成网络流里面每个流的费用,流量都设置成1这样就代表每条路径只能使用1次。增加2个点,源点和汇点,因为来回,就把源点到1建立一条流,流量为2(来回)费用为0,同样N到汇点建立一条流,流量为2费用为0。这样一个网络流就出来了。
这里费用流的增广路径是用spfa来找的,也就是找从源点到汇点流1个单位的流量最小的花费。这题找到路径后就进行正常的网络流增广路了,就是算费用的时候用+=N那个点的费用乘这个路径的最大流量
举个例子就比如坐车,要从a->g,途中要经过转车,每上一次车都要交钱,你一个人从a坐到g要花10块钱,然后你们组团一起坐车,问你一趟要花多少钱(一趟中人数是依据最小的车子能载几个人)。费用流的增广路就是这样,先找到这个路径,在看路径中的最大流量算出这条路径的费用。
用spfa不用dijkstra的原因是因为我们建立反向边的时候费用是正向边费用的负数,存在了负权值就不能用dijkstra了。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int MAXN = 1010;
const int MAXM = 40010;

typedef struct Node{
    int s,to,next,capacity,value;
}Node;

int n,m;
int ecnt;
Node node[MAXM];
int pre[MAXN];
int head[MAXN];
int dis[MAXN];
bool vis[MAXN];

void init()
{
    ecnt = 0;
    memset(head,-1,sizeof(head));
    memset(node,0,sizeof(node));
}

void addEdge(int u,int v,int w,int c)
{
    node[ecnt].to = v;
    node[ecnt].s = u;
    node[ecnt].capacity = c;//流量
    node[ecnt].value = w;//路径长度是费用
    node[ecnt].next = head[u];
    head[u] = ecnt++;
    node[ecnt].to = u;
    node[ecnt].s = v;
    node[ecnt].capacity = 0;//流量
    node[ecnt].value = -w;//路径长度是费用
    node[ecnt].next = head[v];
    head[v] = ecnt++;
}

bool spfa(int s,int t,int nnum)
{
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    for(int i = 0;i <= nnum;++i)
    {
        dis[i] = inf;
    }
    queue<int>que;
    que.push(s);
    dis[s] = 0;
    vis[s] = true;
    while(!que.empty())
    {
        int temp = que.front();
        que.pop();
        vis[temp] = false;
        for(int i = head[temp];i + 1;i = node[i].next)
        {
            if(node[i].capacity)
            {
                int ne = node[i].to;
                if(dis[temp] + node[i].value < dis[ne]){
                    dis[ne] = dis[temp] + node[i].value;
                    pre[ne] = i;
                    if(!vis[ne]){
                        que.push(ne);
                        vis[ne] = true;
                    }
                }
            }
        }
    }
    if(dis[t] == inf)
        return false;
    return true;
}

int getMincost(int s,int t,int nnum)
{
    int ans_flow = 0;
    int ans_cost = 0;
    int temp,minc;
    while(spfa(s,t,nnum))
    {
//        cout << 0 << endl;
        temp = t;
        minc = inf;
        while(pre[temp] != -1)
        {
            minc = min(node[pre[temp]].capacity,minc);
            temp = node[pre[temp]].s;
        }
        temp = t;
        while(pre[temp] != -1)
        {
            node[pre[temp]].capacity -= minc;
            int ss = pre[temp] ^ 1;
            node[ss].capacity += minc;
            temp = node[pre[temp]].s;
        }
        ans_cost += dis[t] * minc;
    }
    return ans_cost;
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        int u,v,c,w;
        int s,t,result;
        init();
        for(int i = 0;i < m;++i)
        {
            scanf("%d %d %d",&u,&v,&w);
            addEdge(u,v,w,1);
            addEdge(v,u,w,1);
        }
        s = n + 1;
        t = s + 1;
        addEdge(s,1,0,2);
        addEdge(n,t,0,2);
//        cout << 0 << endl;
        result = getMincost(s,t,t);
        printf("%d\n",result);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/80196734