POJ 2135 Farm Tour 費用流

Farm Tour
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 11005   Accepted: 4072

Descriptionide

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.

Inputspa

* 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.

Outputcode

A single line containing the length of the shortest tour.

Sample Inputblog

4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2

Sample Outputip

6

Sourceget

 
題目大意:n個點,m條無向邊,起點始終爲1,終點始終爲n,問從起點走到終點再從終點走到起點通過的最短路徑是多少。
 
題目分析:將起點走到終點再走回起點轉化爲兩次從起點走到終點且不走重複邊,創建超級源匯鏈接起點和終點,容量爲2,費用爲1,其餘按照題目建邊跑一遍最小費用流便可。
 
代碼以下:
 
#include <stdio.h>
#include <string.h>
#include <memory.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define REP(i, n) for(int i = 0; i < n; ++i)
const int maxE = 1000000;
const int maxN = 1005;
const int oo = 0x3f3f3f3f;
struct Edge{
    int v, c, w, n;
};
Edge edge[maxE];
int adj[maxN], l;
int d[maxN], cur[maxN], a[maxN];
int inq[maxN], Q[maxE], head, tail;
int n, m;
int cost, flow, s, t;
void addedge(int u, int v, int c, int w){
    edge[l].v = v; edge[l].c = c; edge[l].w =  w; edge[l].n = adj[u]; adj[u] = l++;
    edge[l].v = u; edge[l].c = 0; edge[l].w = -w; edge[l].n = adj[v]; adj[v] = l++;
}
int SPFA(){
    memset(d, oo, sizeof d);
    memset(inq, 0, sizeof inq);
    head = tail = 0;
    d[s] = 0;
    a[s] = oo;
    cur[s] = -1;
    Q[tail++] = s;
    while(head != tail){
        int u =  Q[head++];
        inq[u] = 0;
        for(int i = adj[u]; ~i; i = edge[i].n){
            int v = edge[i].v;
            if(!edge[i].c || d[v] <= d[u] + edge[i].w) continue;
            d[v] = d[u] + edge[i].w;
            cur[v] = i;
            a[v] = min(edge[i].c, a[u]);
            if(inq[v]) continue;
            inq[v] = 1;
            Q[tail++] = v;
        }
    }
    if(d[t] == oo) return 0;
    flow += a[t];
    cost += a[t] * d[t];
    for(int i = cur[t]; ~i; i = cur[edge[i ^ 1].v]){
        edge[i].c -= a[t];
        edge[i ^ 1].c += a[t];
    }
    return 1;
}
int MCMF(){
    flow = cost = 0;
    while(SPFA());
    return cost;
}
void work(){
    int u, v, w;
    memset(adj, -1, sizeof adj);
    l = 0;
    s = 0; t = n + 1;
    while(m--){
        scanf("%d%d%d", &u, &v, &w);
        addedge(u, v, 1, w);
        addedge(v, u, 1, w);
    }
    addedge(s, 1, 2, 0);
    addedge(n, t, 2, 0);
    printf("%d\n", MCMF());
}
int main(){
    while(~scanf("%d%d", &n, &m)) work();
    return 0;
}
POJ 2135
相關文章
相關標籤/搜索