POJ 2112 /// 最大流+floyd+二分
题目大意:
有 k台挤奶机 和 c头奶牛
每台挤奶机最多为m头奶牛服务
给定所有挤奶机和奶牛两两之间的距离
求一种分配 使得 奶牛与挤奶机之间的最远距离 最小化
floyd求得所有挤奶机与奶牛两两之间的最短距离
二分一个最远距离M 建图
超级源点s与所有奶牛连容量为1的边
所有挤奶机与超级汇点t连容量为m的边
奶牛与挤奶机之间距离<=M的连容量为1的边
跑s到t的最大流 若最大流为c 说明这个最远距离M是符合要求的
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; #define LL long long #define INF 0x3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) const int N=300; int d[N][N],L,R; int n,m,s,t; /**Dinic*/ struct NODE { int v,w,r; }; vector <NODE> E[N]; void addE(int u,int v,int w) { E[u].push_back({v,w,E[v].size()}); E[v].push_back({u,0,E[u].size()-1}); } int lev[N], cur[N]; bool bfs(int s,int t) { mem(lev,0); lev[s]=1; queue <int> q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<E[u].size();i++) { NODE e=E[u][i]; if(e.w>0 && !lev[e.v]) { lev[e.v]=lev[u]+1; q.push(e.v); } } } return lev[t]>0; } int dfs(int s,int t,int f) { if(s==t) return f; for(int& i=cur[s];i<E[s].size();i++) { NODE& e=E[s][i]; if(e.w>0 && lev[s]<lev[e.v]) { int d=dfs(e.v,t,min(f,e.w)); if(d>0) { e.w-=d; E[e.v][e.r].w+=d; return d; } } } return 0; } int maxFlow(int s,int t) { int flow=0, f; while(bfs(s,t)) { mem(cur,0); while((f=dfs(s,t,INF))>0) flow+=f; } return flow; } /***/ bool check(int k,int c,int m,int M) { for(int i=0;i<=n+1;i++) E[i].clear(); s=0,t=n+1; for(int i=k+1;i<=n;i++) addE(s,i,1); for(int i=1;i<=k;i++) addE(i,t,m); for(int i=k+1;i<=n;i++) for(int j=1;j<=k;j++) if(d[i][j]<=M) addE(i,j,1); return maxFlow(s,t)==c; } void floyd(int k,int c) { L=INF, R=-INF; for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { d[i][j]=min(d[i][j],d[i][k]+d[k][j]); L=min(L,d[i][j]); R=max(R,d[i][j]); } } int main() { int k,c,m; while(~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",&d[i][j]); if(i!=j && !d[i][j]) d[i][j]=INF; } floyd(k,c); int ans=0; while(L<=R) { int M=(L+R)>>1; if(check(k,c,m,M)) ans=M,R=M-1; else L=M+1; } printf("%d\n",ans); } return 0; }