码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 2135 Farm Tour

时间:2015-11-08 19:19:55      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:

和UVA - 1658 Admiral如出一撤,就是跑一个流量为2的最小费用流。

主要来学习一下用dijkstra处理负边权来增广,主要思想是每个点都维护一个顶标h[v],叫做v的势。

对于每个边ei(u,v)(u到v的有向边),修正它们的边权w[i] 为w‘[i] = w[i] + h[u] - h[v]。看上去有点奇怪?别急,待会可以看到h的作用。

通过适当取h的值可以保证修正后的边权都非负。取h[x]为当前残留网络下s到u的最短距离, 显然有h[v] ≤ h[u] + w[i],w‘[i] ≥ 0,而且可以

知道只有ei在最短路上,w‘[i] = 0。具体的维护方法可以看代码注释。

复杂度

用spfa(队列优化的Bellman-Ford)增广的复杂度是O(F*V*E),用dijkstra增广则可以降低到O(F*V^2)或者O(F*E*logV)。

因为实际实现用优先队列,不能修改优先级,且优先队列重载的容器是vector,vector首次扩容是nlogn的。(因此不要把优先队列定义在循环内,pd_ds库里有堆的黑科技)

这题上dijkstra实际运行时间甚至比spfa要长。(只要不是出题人有意卡数据一般没问题,而且费用流大多数人用的是spfa吧。)

code贴版(大雾)

/*********************************************************
*            ------------------                          *
*   author AbyssalFish                                   *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;


const int maxn = 2505;

template<typename T>
struct BinaryHEAP
{
    T Heap[maxn];
    int sz;
    #define Cmp(a,b) ((a)<(b)) //small
    void push(const T &x)
    {
        int i = ++sz;
        while(i > 1){
            int p = i>>1;
            if(!Cmp(x,Heap[p])) break;
            Heap[i] = Heap[p]; //如果复杂结构体改成指针
            i = p;
        }
        Heap[i] = x;
    }

    void pop()
    {
        T &x = Heap[sz--];
        int i = 1;
        while((i<<1)<=sz){
            int a = i<<1, b = i<<1|1;
            if(b<=sz && Cmp(Heap[b],Heap[a])) a = b;
            if(!Cmp(Heap[a],x)) break;
            Heap[i] = Heap[a];
            i = a;
        }
        Heap[i] = x;
    }

    T &operator[](int x){ return Heap[x]; }
};


const int maxv = 1000, maxe = 4e4;
int hd[maxv],to[maxe],nx[maxe],ec,cap[maxe],cost[maxe];
#define eachEage int i = hd[u]; ~i; i = nx[i]
void add(int u,int v,int cp,int cst)
{
    nx[ec] = hd[u];
    to[ec] = v;
    cap[ec] = cp;
    cost[ec] = cst;
    hd[u] = ec++;
}


void Add(int u,int v,int cp,int cst)
{
    add(u,v,cp,cst); add(v,u,0,-cst);
}

bool inq[maxv];
int dist[maxv], prve[maxv];
int pot[maxv]; //
const int INF = 0x3f3f3f3f;

typedef pair<int,int> hNode;
#define fi first
#define se second
int Ver;//vertex count

BinaryHEAP<hNode> q;

int minCostMaxFlow(int s,int t,int f)
{
    int cst = 0;
    int *const d = dist, *const p = prve;
    int *const h = pot;//维护 h[u] 表示当前残留网络下s到u的最短距离
    //memset(pot,0,sizeof(int)*Ver);
    while(f>0){
        memset(dist,0x3f,sizeof(int)*Ver);
        q.push(hNode(d[s] = 0, s));
        while(q.sz){
            hNode x = q[1]; q.pop();
            int u = x.second;
            if(u == t) {
                q.sz = 0;
                break;
            }
            if(d[u] < x.first) continue;
            for(eachEage){
                int v = to[i];
                if(cap[i] && d[v] > d[u] + cost[i] + h[u] - h[v]){ //边距离修正u->v, 根据h的定义,h[v] <= w[e] + h[u]
                    d[v] = d[u] + cost[i] + h[u] - h[v];//最短路径上修正值累加得出的d[v] = d‘[v](实际值) - h[v] (h[s] = 0)
                    p[v] = i;
                    q.push(hNode(d[v], v));
                }
            }
        }
        if(d[t] == INF) break;
        for(int i = 0; i < Ver; i++) h[i] += d[i]; //如果d[i] = INF ???

        /* 本题中a == 1
        int a = f; // augment flow
        for(int v = t, e; v != s; v = to[e^1]){
            e = p[v];
            if(cap[e] < a) a = cap[e];
        }
        */
        cst += h[t]; // a*h[t]
        f --; // -= a

        for(int v = t, e; v != s; v = to[e^1]){
            e = p[v];
            cap[e] --; // -= a;
            cap[e^1] ++;// -= a;
        }
    }
    return cst;
}


//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int n, m; scanf("%d%d",&n,&m);
    Ver = n;
    memset(hd,0xff,sizeof(int)*Ver);

    for(int i = 0; i < m; i++){
        int a,b,c; scanf("%d%d%d",&a,&b,&c);
        Add(--a,--b,1,c);
        Add(b,a,1,c);
    }
    printf("%d\n",minCostMaxFlow(0,n-1,2));
    return 0;
}

 

POJ 2135 Farm Tour

标签:

原文地址:http://www.cnblogs.com/jerryRey/p/4947814.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!