poj 2112

来源:互联网 发布:成捷迅线路绘图软件 编辑:程序博客网 时间:2024/05/16 10:04

网络流之最大流。此题的关键就是建模,看了题目之后一点思路都没有,后来在网上看了解题报告后,才明白了这个过程。首先,在原图中抽象出一个新图。新图是由旧图中的每个milking machine到每个cow的最短路径组成,每条最短路径由原图中的各点间的某些路径组成,抽象为新图中的一条路径,此过程通过floyd算法(各顶点间的最短路径)实现。接下来,就是通过二分来枚举答案。通过给出一个流量的上限,给新图的路径的容量cap赋值,如果小于等于上限cap就为1,反之为0。最后就可将问题转化为新图中,从各milk machine(即源点s)到各cow(即终点t)的最大流(一个流就对应与一头牛)(其实还不完整),如果最大流>=cow的个数,说明当前方案可行,枚举下一个值,最后由二分得到最优解。其中多源多终点问题,可通过加一个超级源和超级终点来转换为一源一终最大流问题。其实,还有一个问题没有解决,就是每台milk machine最大的工作量为m,现在有个超级源就可以很完美的规划为网络流问题。通过设定超级源到每个源点的容量为m,那么由流网络中的流守恒定理可知,从超级源流到各源的上限就是个从各源流出的流的上限,也即各milk machine所能服务的cow的上限。还有一个很明显的问题就是,一个牛肯定只能接受一个流,所以设定各个终点到超级终点的路径的容量设为1。其中最大流算法用的是EK,很慢,但目前还没掌握dinic和isap,这几天要抓紧学啊。

#include <iostream>#include <cstring>#include <cstdio>#include <queue>using namespace std;const int maxn=250;const int inf=1<<20;//刚开始inf定义的过大,导致求dis[i][j]时,使两个inf相加的和溢出,得到一个错的dis[i][j],以后要注意这个问题int dis[maxn][maxn],cap[maxn][maxn],flow[maxn][maxn];int k,c,m,t;void floyd(){int i,j,k;for(k=1;k<=t;k++){for(i=1;i<=t;i++){for(j=1;j<=t;j++)dis[i][j]=dis[i][j]<(dis[i][k]+dis[k][j])?dis[i][j]:(dis[i][k]+dis[k][j]);//防止溢出,所以inf不能定义的过大}}}void build(int limit){memset(cap,0,sizeof(cap));int i,j;for(i=1;i<=k;i++) cap[0][i]=m;for(i=k+1;i<=t;i++) cap[i][t+1]=1;for(i=1;i<=k;i++){for(j=k+1;j<=t;j++)if(dis[i][j]<inf&&dis[i][j]<=limit) cap[i][j]=1;}}bool ek(){queue<int> q;int a[maxn],p[maxn],tot=0,i;memset(flow,0,sizeof(flow));for(;;){memset(a,0,sizeof(a));a[0]=inf;q.push(0);while(!q.empty()){int x=q.front();q.pop();for(i=0;i<=t+1;i++){if(!a[i]&&(cap[x][i]-flow[x][i])>0){p[i]=x;a[i]=a[x]>(cap[x][i]-flow[x][i])?(cap[x][i]-flow[x][i]):a[x];q.push(i);}}}if(!a[t+1]) break;for(i=t+1;i!=0;i=p[i]){flow[p[i]][i]+=a[t+1];flow[i][p[i]]-=a[t+1];}tot+=a[t+1];}if(tot<c) return false;else return true;}int binarysearch(){int high=230*200+1,low=0,mid;while(high-low>0){mid=low+(high-low)/2;build(mid);if(ek()) high=mid;else low=mid+1;}return high;}int main(){while(scanf("%d%d%d",&k,&c,&m)!=EOF){int i,j;t=k+c;for(i=1;i<=t;i++){for(j=1;j<=t;j++){scanf("%d",&dis[i][j]);if(!dis[i][j]&&i!=j) dis[i][j]=inf;}}floyd();int result=binarysearch();cout<<result<<endl;}return 0;}


原创粉丝点击