poj2112解题报告(最大流 EK算法)
2015-07-21 16:45
281 查看
题目大意:
k个机器,每个机器最多服务m头牛。
c头牛,每个牛需要1台机器来服务。
告诉你牛与机器每个之间的直接距离。
问:让所有的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离。
解题思路:
Floyd求出各个点之间最短距离,二分枚举最短距离(上界是最大的最短距离,下界是最小的最短距离),Ek算法建图的注意最小距离大于mid的距离不给容量。
注意点:邻接举证为0的点是无限大.注意这个地方,有些时候需要判断一发
k个机器,每个机器最多服务m头牛。
c头牛,每个牛需要1台机器来服务。
告诉你牛与机器每个之间的直接距离。
问:让所有的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离。
解题思路:
Floyd求出各个点之间最短距离,二分枚举最短距离(上界是最大的最短距离,下界是最小的最短距离),Ek算法建图的注意最小距离大于mid的距离不给容量。
注意点:邻接举证为0的点是无限大.注意这个地方,有些时候需要判断一发
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn=250; const int INF=99999999; int n,m,sum,s1,t1;//s,t为始点和终点 int flow[maxn][maxn],cap[maxn][maxn],a[maxn],p[maxn],d[maxn][maxn],k,c,milks; //分别为:flow[u][v]为<u,v>流量、cap[u][v]为<u,v>容量、a[i]表示源点s到节点i的路径上的最小残留量、p[i]记录i的前驱 void Edmonds_Karp(int s,int t) { int i,u,v; queue<int>q;//队列,用bfs找增广路 while(1) { memset(a,0,sizeof(a));//每找一次,初始化一次 a[s]=INF; q.push(s);//源点入队 while(!q.empty()) { u=q.front(); q.pop(); for(v=1; v<=m; v++) { if(!a[v]&&flow[u][v]<cap[u][v]) { p[v]=u; q.push(v); a[v]=min(a[u],cap[u][v]-flow[u][v]);//s-v路径上的最小残量 } } } if(a[t]==0)//找不到增广路,则当前流已经是最大流 break; sum+=a[t];//流加上 for(i=t; i!=s; i=p[i]) // //从汇点顺着这条增广路往回走 { // cout<<i<<" "; flow[p[i]][i]+=a[t];//更新正向流量 flow[i][p[i]]-=a[t];//更新反向流量 } // cout<<endl; } } int main() { int v,u,w; while(scanf("%d%d%d",&k,&c,&milks)!=EOF)//n是边数,m是点数 { int up=-1; int down=INF; for(int i=1; i<=c+k; i++) for(int j=1; j<=c+k; j++) scanf("%d",&d[i][j]); for(int k1 = 1; k1 <= c+k; k1++) for(int i = 1; i <= c+k; i++) for(int j = 1; j <= c+k; j++) if(d[i][k1]&&d[k1][j]&&(d[i][j]==0||d[i][j]>d[i][k1] + d[k1][j])) { d[i][j]=d[i][k1] + d[k1][j]; up=max(up,d[i][j]); down=min(down,d[i][j]); } m=c+k+2; t1=c+k+2; s1=c+k+1; int ans=up; // down=0;up=ans; while(down<=up) { int mid=(down+up)/2; sum=0;//记录最大流量 memset(flow,0,sizeof(flow));//初始化 memset(cap,0,sizeof(cap)); for(int i=1; i<=k; i++) //源点到挤奶机 cap[s1][i]=milks; for(int i=k+1; i<=k+c; i++) //奶牛到汇点 cap[i][t1]=1; for(int i = 1; i <= k; i++)//挤奶机到奶牛 for(int j = k + 1; j <=k+ c; j++) cap[i][j] = (d[i][j] != 0 && d[i][j] <= mid); Edmonds_Karp(s1,t1); // cout<<down<<" "<<up<<" "<<sum<<endl; if (sum == c) { if(mid < ans) ans = mid; up = mid - 1; } else down = mid + 1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- 注册表-删不掉的桌面快捷
- MySQL的基本数据类型与数据类型优化
- 如何设置apple watch的interface controller 标题的color?
- 解决nginx不支持thinkphp中pathinfo的问题
- zabbix安装及过程中遇到的问题总结
- Android ContentProvider+ContentObserver
- mysql中where字句的特殊用法
- 2015年ALPC暑期专题练习I (计算几何) F Pick-up sticks
- 欢迎使用CSDN-markdown编辑器
- 利用线性表实现集合A并上B
- android加载长图片出现Bitmap too large to be uploaded into a texture的解决方案
- Xpath常用函数
- RESTful API URI 设计: 判断资源是否存在?
- WPF三种基本触发器与【与或】逻辑触发器
- LINUX 下时间转换为秒数
- c#快捷键大全
- Oracle 11g统计信息收集--多列统计信息的收集
- 【设计模式】动态代理设计模式
- java创建日期
- 计算机蓝屏了,一天5次很开心