1. 程式人生 > >poj 2135 Farm Tour(費用流)

poj 2135 Farm Tour(費用流)

                                                                                    Farm Tour

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 20591 Accepted: 7929

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

這道題的題意是,在一個無向圖中,從1點找出一條路徑使到達n點的距離最短,並在從n點走不同的路回到1點。

乍一看這是個最短路的問題,只不過是要求兩次,並且不能重複走相同的路徑。

所以我們總不能求兩次最短路吧,再看一下題,從n點回到1點和從1點到n點其實是一樣的,所以可以等價為求出最短的兩條從1點到n點距離最短的路徑,那麼是不是可以看成這個圖中,最大流量為2呢?並且不能走重複的路,那麼每條邊的流量設為1不就好了?而花費就是每條邊的長度。

這樣問題就轉化成了求出一個無向圖中最大流為2,每條邊的流量都為1的最小費用。這樣的話我們再加上兩個點,源點s和匯點t,設定成s->1,流量為2,花費0,n->t,流量為2,花費為0。這樣圖就構建完成了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e6+10;
int n,m,tot,s,t,mincost,maxflow;
int head[N],dis[N],pre[N],path[N],vis[N];          //dis陣列為求出的到達一點的最小費用
struct node
{
    int v;
    int w;
    int next;
    int cost;
    node()
    {
        v=0;
        w=0;
        next=-1;
        cost=0;
    }
}e[N];
void add(int u,int y,int z,int co)
{
    e[++tot].v=y;
    e[tot].w=z;
    e[tot].next=head[u];
    e[tot].cost=co;
    head[u]=tot;

    e[++tot].v=u;
    e[tot].w=0;
    e[tot].cost=-co;
    e[tot].next=head[y];
    head[y]=tot;
}
bool spfa()
{
    queue<int>q;
    met(dis,inf);
    met(pre,0);
    met(path,0);
    met(vis,false);
    vis[s]=true;
    dis[s]=0;
    while(!q.empty())
        q.pop();
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(dis[v]>e[i].cost+dis[u]&&e[i].w>0){
                dis[v]=e[i].cost+dis[u];
                pre[v]=u;         //前一個點
                path[v]=i;     //前一個邊
            if(!vis[v]){
                vis[v]=true;
                q.push(v);
            }
          }
        }
    }
    if(dis[t]==inf)
        return false;
    return true;
}
void minf()
{
     maxflow=0;
     mincost=0;
    while(spfa()){
        int f=inf;
        for(int i=t;i!=s;i=pre[i]){
            if(e[path[i]].w<f)
                f=e[path[i]].w;
        }
        mincost+=f*dis[t];
        maxflow+=f;
        for(int i=t;i!=s;i=pre[i]){
            e[path[i]].w-=f;          //正向邊減少容量
            e[path[i]^1].w+=f;         //反向邊增加流量
        }
    }
}
void init()
{
    tot=-1;
    met(head,-1);
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
            int x,y,f;
            init();
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&f);
            add(x,y,1,f);
            add(y,x,1,f);
        }
        s=n+1;
        t=s+1;
        add(s,1,2,0);
        add(n,t,2,0);
        minf();
        printf("%d\n",mincost);
    }
}