poj2135(简单的最小费用流问题)

题目链接:http://poj.org/problem?id=2135


Farm Tour

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10862   Accepted: 4024

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

USACO 2003 February Green

[Submit]   [Go Back]   [Status]  
[Discuss]

将问题转换为从1号节点到N号节点的两条没有公共边的路径即可。这样就转换成了,求流量为2的最小费用流。

code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXV=10010;
const int MAXM=10010;
const int INF=1<<30;
typedef pair<int,int> P;
struct edge{int to,cap,cost,rev;};
int V;
vector<edge> G[MAXV];
int h[MAXV];
int dist[MAXV];
int prevv[MAXV],preve[MAXV];
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,0,-cost,G[from].size()-1});
}
int min_cost_flow(int s,int t,int f)
{
    int res=0;
    fill(h,h+V,0);
    while(f>0)
    {
        priority_queue<P,vector<P>,greater<P> >que;
        fill(dist,dist+V,INF);
        dist[s]=0;
        que.push(P(0,s));
        while(!que.empty())
        {
            P p=que.top();
            que.pop();
            int v=p.second;
            if(dist[v]<p.first)
            {
                continue;
            }
            for(int i=0;i<G[v].size();i++)
            {
                edge &e=G[v][i];
                if(e.cap>0&&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 -1;
        }
        for(int v=0;v<V;v++) h[v]+=dist[v];
        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 a[MAXM],b[MAXM],c[MAXM];
void solve()
{
    int s=0,t=N-1;
    V=N;
    for(int i=0;i<M;i++)
    {
        add_edge(a[i]-1,b[i]-1,1,c[i]);
        add_edge(b[i]-1,a[i]-1,1,c[i]);
    }
    cout<<min_cost_flow(s,t,2)<<endl;
}
int main()
{
    while(cin>>N>>M)
    {
        for(int i=0;i<M;i++)
        {
            scanf("%d%d%d",&a[i],&b[i],&c[i]);
        }
        solve();
    }
    return 0;
}

poj2135(简单的最小费用流问题)

时间: 2024-11-08 04:27:24

poj2135(简单的最小费用流问题)的相关文章

POJ2135 Farm Tour 最小费用流

给出一个图,从一号节点去N号节点,再回来. 但是不能经过相同的边,即一条边最多只能够走一次. 求来回的总长度的最小值. 转化: 求1号到N号的2条没有公共边的路径,这样就相当于在这个图中所有边的容量都是1,现在要找2条增广路,得到的流量为2,就相当于求流量为2的最小费用流. 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<vector> 5 6 using namespa

poj2135 最小费用流

添加超级源点(与点1之间的边容量为2,权值为0)和超级汇点(与点N之间的边容量为2,权值为0),求流量为2的最小费用流.注意是双向边. #include <iostream> #include <cstdio> #include <vector> #include <queue> using namespace std; const long long INF = 0x3f3f3f3f3f3f3f3f; typedef long long ll; typed

poj2135最小费用流

裸题,就是存个模板 最小费用流是用spfa求解的,目的是方便求解负环,spfa类似于最大流中的bfs过程 #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert> #include<iomanip> #i

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

POJ 2195Going Home(网络流之最小费用流)

题目地址:POJ2195 本人职业生涯费用流第一发!!快邀请赛了,决定还是多学点东西,起码碰到简单的网络流要A掉.以后最大流费用流最小割就一块刷. 以前费用流在我心目中一直是高大上,高不可攀的形象,可这两天才发现,原来费用流就是一个spfa再加点东西...一直以为费用流会比最大流的isap要麻烦好多,毕竟多了一个费用的元素....我真的错了..仔细研究了一下,只用一个spfa确实就可以解决了... 这题是一个入门题(虽然还多了些处理..),建图思路很简单,就是将人与源点相连,流量为1,费用为0,

POJ 2195 最小费用流

点击打开链接 题意:给个乱七八糟的方阵,H代表家,m代表人,现在所有人都要回到一个家,问所有人走到家的步数和 思路:还是很好想到费用流的,费用为人走到家的步数,求最小,流量即为人的个数,连边的话,每个人都连到家的容量为1,费用为步数的边,建立超级源点与人相连,容量为1,费用为0,家与超级汇点相连,一样容量为1肥育馆为0,跑最小费用流就是结果了,PS:入门题,还是蛮简单的......... #include <queue> #include <vector> #include <

[转]从入门到精通: 最小费用流的“zkw算法”

>>>> 原文地址:最小费用流的“zkw算法” <<<< 1. 网络流的一些基本概念 很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本的概念反而说不清楚. 虽然不同的模型在具体叫法上可能不相同, 但是不同叫法对应的思想是一致的. 下面的讨论力求规范, 个别地方可能需要对通常的叫法加以澄清. 求解可行流: 给定一个网络流图, 初始时每个节点不一定平衡 (每个节点可以有盈余或不足), 每条边的流量可以有上下界, 每条边的当前流量可以不满足上下界

MZL&#39;s City (hdu 5352 最小费用流 ||二分图匹配)

MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 719    Accepted Submission(s): 251 Problem Description MZL is an active girl who has her own country. Her big country has N cities num

解题报告 之 POJ2135 Farm Tour

解题报告 之 POJ2135 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.