Farm Tour-最小费用最大流/SPFA

来源:互联网 发布:新型网络诈骗手段新闻 编辑:程序博客网 时间:2024/04/28 00:36

Farm Tour

问题来源:poj-2135


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

源代码:
#include<iostream>#include<cstring>#include<queue>using namespace std;struct Edge{    int from , to , cost , cap , next;};queue <int> Q;const int MAXN = 1002;const int MAX = 40008;const int INF = 1<<29;int  N , M , S , T , num;int  head[MAXN] , pre[MAXN] , dis[MAXN];bool mark[MAXN];Edge edge[MAX];//head是邻接表的首节点所在edge的索引//pre是点在邻接表的索引//dis是SPFA算法的距离(离源点)bool SPFA( void );int  update( void );int  minCost( void );void add_edge( int a , int b , int c , int f );int main( ){    int i , a , b , c;    while( cin>>N>>M ){        num = 0;        S = 0;        T = N + 1;        memset( head , -1 , sizeof( head ) );        for( i=1 ; i<=M ; i++ ){            cin>>a>>b>>c;            add_edge( a , b , c , 1 );            add_edge( b , a , c , 1 );        }        add_edge( S , 1 , 0 , 2 );        add_edge( N , T , 0 , 2 );        cout<<minCost()<<endl;    }    return 0;}void add_edge( int a , int b , int c , int f ){    edge[num].from = a;    //正向边    edge[num].to = b;    edge[num].cost = c;    //费用为正    edge[num].cap = f;    //容量为正    edge[num].next = head[a];    head[a] = num++;    edge[num].from = b;    //负向边    edge[num].to = a;    edge[num].cost = -c;    //费用为负    edge[num].cap = 0;    //容量为0    edge[num].next = head[b];    head[b] = num++;}int  minCost( void ){    int sum = 0;    while( SPFA( ) ){        sum += update( );    }    return sum;}bool SPFA( void ){    int i , j , u , v;    memset( mark , false , sizeof( false ) );    memset( pre , -1 , sizeof(  pre) );    for( i=S ; i<=T ; i++ )    dis[i] = INF;    while( !Q.empty( ) )    Q.pop( );    dis[S] = 0;    Q.push( S );    mark[S] = true;        while( !Q.empty( ) ){        u = Q.front( );        Q.pop( );        //与BFS不同点一:新节点要做松弛操作        mark[u] = false;                //与BFS不同点二:SPFA算法没有终止条件        for( j=head[u] ; j!=-1 ; j=edge[j].next ){            v = edge[j].to;            if( edge[j].cap && dis[u]+edge[j].cost<dis[v] ){                dis[v] = dis[u] + edge[j].cost;                pre[v] = j;                if( !mark[v] ){                    Q.push( v );                    mark[v] = true;                }            }        }    }    if( pre[T]==-1 )        return false;    return true;}int  update( void ){    int k , u , v;    k = pre[T];    while( k!=-1 ){        edge[k].cap--;    //容量减少1        edge[k^1].cap++;    //反向容量增1        k = pre[edge[k].from];    //寻找上一个节点在edge中的位置    }    return dis[T];}

代码分析:最小费用最大流的一个模板,数据结构使用了静态数组来实现邻接表,同时用了SFPA算法求最短路,我觉得加边的那部分是精华,看帖写的,也不是太明白为什么要加成4条边,还求大神解释啊

0 0
原创粉丝点击