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;
    }
  • 相关阅读:
    ios中解析json对象基类
    iOS archive(归档)的总结
    ios block一定会犯的几个错误
    iOS求职之C语言面试题
    iOS求职之OC面试题
    iOS开发之17个常用代码整理
    91平台iOS接入demo
    IOS 启动画面和图标设置(适配IOS7 and Xcode5)
    iOS - 切换图片/clip subview/iCarousel
    jemter多种方式查看结果树及正则的使用
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7895439.html
Copyright © 2011-2022 走看看