zoukankan      html  css  js  c++  java
  • POJ 2195 Going Home【最小费用最大流】

    刚读的时候以为是Optimal Milking那道题,但实际上不是的;但借此我也想清了一些东西。

    optimal milking里面问的是走的最远的那头奶牛最少走多少,对应到这道题里就是走的最远的people最少走多少;若是这样的话就得二分找可行流了,不然的话没有办法建图。(几乎一样的题稍微问了个不一样的东西,就从原本用最大流解变成用费用流解,让我觉得很奇妙)

    这里面问的一共最少走多少,那就是费用流了。

    #include<iostream>
    #include<deque>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #define INF 2e9
    using namespace std;
    
    int T,ans;
    
    struct edge{
        int v,cap,reverse,cost;
    };
    vector<int> edges[1005];//邻接表 
    vector<edge> bian;//所有的边都存在里面
    vector< pair<int,int> > people,house;
    char maze[105][105];
    
    void addedge(int u,int v,int cost,int cap){//u到v一条边,再加一条反向边 
        edge e;
        e.cap=cap;
        e.v=v;
        e.cost=cost;
        e.reverse=bian.size()+1;//这条边的反边将建在这条边之后(这条边建完后在bian.size()的位置) 
        bian.push_back(e);
        edges[u].push_back(bian.size()-1);
        
        e.cap=0;
        e.v=u;
        e.cost=-cost;
        e.reverse=bian.size()-1;
        bian.push_back(e);
        edges[v].push_back(bian.size()-1);
    }
    
    int dist[1005],pre[1005];//pre[i]代表走的哪条边到的i点 
    
    bool spfa(){
        for(int i=0;i<=T;i++) dist[i]=INF;
        for(int i=0;i<=T;i++) pre[i]=-1;
            
        deque<int> q;
        dist[0]=0; pre[0]=-1; q.push_back(0);
        while( !q.empty() ){
            int u = q.front(); q.pop_front();
            for(int i=0;i<edges[u].size();i++){//所有以u为起点的边的边的索引 
                edge &e = bian[ edges[u][i] ];
                int v=e.v;
                if( e.cap>0 && dist[u]+e.cost<dist[v] ){
                    dist[v] = dist[u]+e.cost;
                    pre[v]=edges[u][i];
                    q.push_back(v);
                }
            }
        }
        
        if(dist[T]==INF) return false;
        return true;
    }
    
    int EK(){
        int max_flow=0;
        while( spfa() ){
            //cout<<"suc"<<endl;
            int u=T,minflow=INF;//在终点位置
            while( u!=0 ){
                edge &e = bian[ pre[u] ];
                minflow=min(minflow,e.cap);
                u = bian[ e.reverse ].v;
            }
            ans+=minflow*dist[T];
            u=T;
            while( u!=0 ){
                edge &e = bian[ pre[u] ];
                e.cap-=minflow;
                bian[ e.reverse ].cap+=minflow;
                u = bian[ e.reverse ].v;
            }
        }
        return max_flow;
    }
    
    int main(){
        int n,m,k;        
            
        while(1){
            cin>>n>>m;
            if(n==0 && m==0) break;
            
            bian.clear(); people.clear(); house.clear();
            for(int i=0;i<=T;i++) edges[i].clear();        
            ans=0;
            
            //people:1-n   house: n+1 - 2*n
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++){
                    cin>>maze[i][j];
                    if( maze[i][j]=='H' ) house.push_back( make_pair(i,j) );
                    else if( maze[i][j]=='m' ) people.push_back( make_pair(i,j) );
                }
             //people向house建边  费用流 
             for(int i=0;i<people.size();i++){
                 for(int j=0;j<house.size();j++){
                     int dis=0;
                     dis = abs(people[i].first-house[j].first)+abs(people[i].second-house[j].second);
                     addedge( i+1,people.size()+j+1,dis,1 );    
                }    
            }
            
            T=2*people.size()+1;
            //源点到所有人
            for(int i=0;i<people.size();i++) addedge(0,i+1,0,1);
            //house到汇点
            for(int i=0;i<house.size();i++) addedge( people.size()+i+1,T,0,1 ); 
             
             EK(); 
            cout<<ans<<endl;
        }
        
        return 0;    
    }
  • 相关阅读:
    解决android SDK升级慢的问题
    matlab的table数据类型初步接触
    IDL软件初步了解
    将博客搬至CSDN
    使用GEANT4的模拟技术1
    geant4开发平台的构建方案的讨论a
    MFC学习1
    Qt如何学习(参考官方文档)
    我对动态磁盘的想法(不全)
    EGS5在linux系统下安装过程
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9526397.html
Copyright © 2011-2022 走看看