做这个题做得好晕................我花了一下的时间调试程序,没有找出错误的地方,好郁闷.....已经开始怀疑自己最大流的模板了,吃完晚饭和女朋友聊会天后,回来在看这题,惊奇的发现,我在一个地方把n敲成了m,害的我wa了n次,哎.......就为了这个 害我狂交这个题....
题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=2112
这是一道2分搜索+最大流+最短路径题(算法还真多),不过是基础。。
1 先用Floyed求出能达到的任意两点之间的最短路径
2 然后用用dinic求最大流,
3 在2分搜索min_max.
这到题和hdu 2962 相似用2分过的,要是直接枚举的话,会tle;
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define MAX 300 #define INF 99999999 int dis[MAX][MAX]; int map[MAX][MAX]; int sign[MAX][MAX]; int used[MAX]; int k,c,n,m; void Floyed() { for(int k=1; k<=n;k++) for(int i=1;i<=n;i++) if(dis[i][k]!=INF) for(int j=1; j<=n; j++) dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); } void Bulid_Graph(int min_max) { memset(map,0,sizeof(map)); for(int i=k+1;i<=n;i++) map[0][i]=1; for(int i=1;i<=k;i++) map[i][n+1]=m; for(int i=k+1;i<=n;i++) for(int j=1;j<=k;j++) if(dis[i][j]<=min_max) map[i][j]=1; } bool bfs() { memset(used,0,sizeof(used)); memset(sign,0,sizeof(sign)); int queue[100*MAX]={0}; queue[0]=0; used[0]=1; int t=1,f=0; while(f<t) { for(int i=0;i<=n+1;i++) { if(!used[i]&&map[queue[f]][i]) { queue[t++]=i; used[i]=1; sign[queue[f]][i]=1; } } f++; } if(used[n+1]) return true; return false; } int Dinic(int v,int sum) { if(v==n+1) return sum; int os,t; os=sum; for(int i=0;i<=n+1;i++) { if(sign[v][i]) { t=Dinic(i,min(map[v][i],sum)); map[v][i]-=t; map[i][v]+=t; sum-=t; } } return os-sum; } int main() { scanf("%d%d%d",&k,&c,&m); n=k+c; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&dis[i][j]); if(dis[i][j]==0) dis[i][j]=INF; } Floyed(); int head=0,tall=10000; while(head<tall) { int mid=(head+tall)/2; int ans=0; Bulid_Graph(mid); while(bfs()) ans+=Dinic(0,INF); if(ans>=c) tall=mid; else head=mid+1; } printf("%d/n",tall); return 0; }