zoukankan      html  css  js  c++  java
  • [poj2135]Farm Tour(最小费用流)

    解题关键:最小费用流 

    代码一:bellma-ford $O(FVE)$  bellman-ford求最短路,并在最短路上增广,速度较慢

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<vector>
    #define inf 0x3f3f3f3f
    #define MAX_V 10010
    using namespace std;
    typedef long long ll;
    struct edge{int to,cap,cost,rev;};
    int V;
    vector<edge>G[MAX_V];
    int dist[MAX_V];
    int prevv[MAX_V],preve[MAX_V];
    
    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;
        while(f>0){
            fill(dist,dist+V,inf);
            dist[s]=0;
            bool update=true;
            while(update){
                update=false;
                for(int v=0;v<V;v++){
                    if(dist[v]==inf) 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){
                            dist[e.to]=dist[v]+e.cost;
                            prevv[e.to]=v;
                            preve[e.to]=i;
                            update=true;
                        }
                    } 
                }
            }
            if(dist[t]==inf) return -1;
            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*dist[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,t1,t2,t3;
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            memset(G,0,sizeof G);
            V=n;
            for(int i=0;i<m;i++){
                scanf("%d%d%d",&t1,&t2,&t3);
                add_edge(t1-1,t2-1,1,t3);
                add_edge(t2-1,t1-1,1,t3);
            }
            printf("%d
    ",min_cost_flow(0,n-1,2));
        }
        return 0;
    }

     代码二:dijkstra,$O(FElogV)$ 

    这里是通过一个定理

    s到v的最短距离<=s到u的最短距离+dis(e)

    s到u的最短距离+dis(e)-s到v的最短距离>=0

    将原先的距离转化为上述的等效距离,即可保证图中无负权边,所以可以用dijkstra算法堆优化来保证复杂度。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define inf 0x3f3f3f3f
    #define MAX_V 10010
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>P;
    struct edge{int to,cap,cost,rev;};
    int V;
    vector<edge>G[MAX_V];
    int h[MAX_V],dist[MAX_V],prevv[MAX_V],preve[MAX_V];
    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,t1,t2,t3;
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            memset(G,0,sizeof G);
            V=n;
            for(int i=0;i<m;i++){
                scanf("%d%d%d",&t1,&t2,&t3);
                add_edge(t1-1,t2-1,1,t3);
                add_edge(t2-1,t1-1,1,t3);
            }
            printf("%d
    ",min_cost_flow(0,n-1,2));
        }
        return 0;
    }
  • 相关阅读:
    (一)Python入门-6面向对象编程:01面向对象和面向过程区别-对象的进化
    (一)Python入门-5函数:10nonlocal-global-LEGB规则
    (一)Python入门-5函数:09嵌套函数(内部函数)-数据隐藏
    (一)Python入门-5函数:08递归函数
    (一)Python入门-5函数:07lambda表达式和匿名函数-eval()函数
    (一)Python入门-5函数:06参数类型-位置参数-默认值参数-命名参数-可变参数-强制命名参数
    (一)Python入门-5函数:05参数的传递-可变对象-不可变对象-浅拷贝和深拷贝-不可变对象含可变子对象
    (一)Python入门-5函数:04变量的作用域-全局变量-局部变量-栈帧内存分析-效率测试
    Java学习第十二章 之 自定义数据类型的使用
    Java学习第十一章 之 final、static、内部类
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7895439.html
Copyright © 2011-2022 走看看