POJ2112解题报告【网络流-初级-isap+floyd_warshall+二分】

来源:互联网 发布:eclipse mac 稳定版本 编辑:程序博客网 时间:2024/06/15 10:04

题目连接:http://poj.org/problem?id=2112

题意:有C头牛和K个挤奶机,每个挤奶机最多能为M头牛挤奶,他们在农场的不同位置。牛和牛、牛和机器之间可能有路,牛只能沿着路移动。给出路的长度,问要让这些牛都挤完奶,所有牛中走得最远的牛的行走路程最短是多少?

解题思路:首先要建图,把每个牛和挤奶机都看成节点,节点间的边既是他们之间的路的长度。然后用floyd算法,求出每个点之间的最短距离。记录最长的距离,然后二分该距离。再建一个网络流的图,图中包括一个源点、一个汇点、挤奶机的点、牛的点,源点和牛之间都连上容量为1的边,牛和挤奶机之间的距离如果小于mid(之前二分的距离),那么就建立一条容量为1的边,每个挤奶机和汇点之间都建立一条容量为K的边。然后ISAP算法求最大流,如果最大流等于C,向下二分否则向上二分。

算法:ISAP+floyd_walshall+二分

#include<cstdio>#include<cstring>#include<queue>#include<stack>#include<cstdlib>#include<algorithm>#include<iostream>#include<map>#include<string>//#define r(x,date) (*((STRUCT*)x).date)//#define dp(i,j) dp[i][j]//#define dp(i,j,k) dp[i][j][k]#define INF 0x7ffffff#define ff(i,from,to) for(i=from;i<=to;i++)#define rff(i,from,to) for(i=from;i>=to;i--)#define ll long long#define MAX_SIDE 110000#define MAX_NODE 300#define mset(a,num) memset(a,num,sizeof(a))using namespace std;template<class T>bool myfun_upmax(T &a,const T&b){return b>a?a=b,1:0;}template<class T>bool myfun_upmin(T &a,const T&b){return b<a?a=b,1:0;}template<class T>void myfun_swap(T &a,T &b){T temp;temp=a;a=b;b=temp;}template<class T>T myfun_max(const T a,const T b){return a>b?a:b;}template<class T>T myfun_min(const T a,const T b){return a<b?a:b;}int cmp(const void *a,const void *b){    return 0;}inline void readint(int &ret) {char c;do {c = getchar();} while(c < '0' || c > '9');ret = c - '0';while((c=getchar()) >= '0' && c <= '9')ret = ret * 10 + ( c - '0' );}int node[MAX_NODE];struct SIDE{    int to,next,c;    SIDE(){}    SIDE(int to,int next,int c):to(to),next(next),c(c){}}side[MAX_SIDE];int top;void add_side(int u,int v,int c){    side[top]=SIDE(v,node[u],c);    node[u]=top++;    side[top]=SIDE(u,node[v],0);    node[v]=top++;}int START,END,SIZE;int gap[MAX_NODE],pre[MAX_NODE],dis[MAX_NODE],cur[MAX_NODE];int sap(){    int maxflow=0;    int aug=INF;    int u=START,v;    for(int i=0;i<SIZE;i++){        gap[i]=dis[i]=0;        cur[i]=node[i];    }    gap[START]=SIZE;    pre[START]=START;    while(dis[u]<SIZE){        for(int &i=cur[u];i!=-1;i=side[i].next){            v=side[i].to;            if( side[i].c && dis[u]==dis[v]+1)break;        }        if(cur[u]!=-1){            myfun_upmin(aug,side[cur[u]].c);            pre[v]=u;u=v;            if(u==END){                maxflow+=aug;                while(u!=START){                    u=pre[u];                    side[cur[u]].c-=aug;                    side[cur[u]^1].c+=aug;                }                aug=INF;            }        }else{            int min_dis=SIZE;            for(int i=node[u];i!=-1;i=side[i].next){                v=side[i].to;                if(side[i].c && myfun_upmin(min_dis,dis[v]))                    cur[u]=i;            }            if(--gap[dis[u]]==0)break;            ++gap[dis[u]=min_dis+1];            u=pre[u];        }    }    return maxflow;}int K,C;int N;int matrix[MAX_NODE][MAX_NODE];int floyd_warshall(){    int MAX=0;    for(int k=0;k<N;k++){        for(int i=0;i<N;i++)        for(int j=0;j<N;j++){            if(i!=j && matrix[i][k]+matrix[k][j]<matrix[i][j]){                matrix[i][j]=matrix[i][k]+matrix[k][j];                if(matrix[i][j]<INF && matrix[i][j]>MAX)                    MAX=matrix[i][j];            }        }    }    return MAX;}int M;void build(int limit){    //length not less than the limit    top=0;    for(int i=0;i<N+2;i++)node[i]=-1;    for(int i=0;i<K;i++){        for(int j=K;j<N;j++){            if(matrix[i][j]<=limit)                add_side(j,i,1);        }    }    int i;    for(i=0;i<K;i++){        add_side(i,END,M);    }    for(;i<N;i++){        add_side(START,i,1);    }}int solve(int low,int high){    while(low<=high){        int mid=low+(high-low)/2;        build(mid);        int r=sap();        if(r==C)high=mid-1;        else low=mid+1;    }    return low;}int main(){    readint(K);    readint(C);    readint(M);    N=K+C;    START=N;    END=N+1;    SIZE=N+2;    for(int i=0;i<N;i++){        for(int j=0;j<N;j++){            readint(matrix[i][j]);            if(matrix[i][j]==0)matrix[i][j]=INF;        }    }    int max_path=floyd_warshall();    int r=solve(1,max_path);    printf("%d\n",r);    return 0;}