题意:给你k个挤奶器,c头牛,每个挤奶器能放m头牛,问你奶牛需要走的最大距离最小是多少;
解题思路:因为最大距离最小,也就是求最小的距离满足所有牛都能到,所以我们先用floyd跑最短路,把所有点之间的距离算出来后再,对答案进行二分:牛和挤奶器的距离<=二分值的可以连一条边,容量为1;
然后源点和奶牛连一条容量为1的边,挤奶器和汇点连一条容量为m的边,所以二分只是为了看奶牛是否能到达某个挤奶器;
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<queue> #include<cstdio> #define maxn 100500 #define inf 0x3f3f3f3f using namespace std; struct Edge { int next; int to; int w; int fa; }edge[maxn]; int head[maxn]; int x,y; int dist[505][505]; int cnt; int n,m,Start,End; int k,c; int depth[maxn]; void floyd() { for(int l=1;l<=c+k;l++) { for(int i=1;i<=c+k;i++) { for(int j=1;j<=c+k;j++) { if(dist[i][j]>dist[i][l]+dist[l][j]) dist[i][j]=dist[i][l]+dist[l][j]; } } } } void add(int u,int v,int w) { edge[cnt].next=head[u];edge[cnt].to=v; edge[cnt].fa=u;edge[cnt].w=w;head[u]=cnt++; edge[cnt].next=head[v];edge[cnt].w=0; edge[cnt].to=u;edge[cnt].fa=v;head[v]=cnt++; } bool bfs() { memset(depth,0,sizeof(depth)); queue<int>q; q.push(Start); depth[Start]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(depth[v]||edge[i].w<=0) continue; depth[v]=depth[u]+1; q.push(v); } } return depth[End]; } int dfs(int u,int maxflow) { if(u==End) return maxflow; int add=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(depth[v]!=depth[u]+1) continue; if(edge[i].w==0) continue; int tempflow=dfs(v,min(edge[i].w,maxflow-add)); edge[i].w-=tempflow; edge[i^1].w+=tempflow; add+=tempflow; } return add; } int dinic() { int ans=0; while(bfs()) { ans+=dfs(Start,inf); } return ans; } void buildmap(int value) { memset(head ,-1,sizeof(head)); cnt=0; for(int i=k+1;i<=k+c;i++) { add(0,i,1); } for(int i=k+1;i<=k+c;i++) { for(int j=1;j<=k;j++) { if(dist[i][j]<=value) { add(i,j,1); // cout<<i<<" "<<j<<endl; } } } for(int i=1;i<=k;i++) { add(i,k+c+1,m); } } int main() { scanf("%d%d%d",&k,&c,&m); Start=0;End=k+c+1; for(int i=1;i<=k+c;i++) { for(int j=1;j<=k+c;j++) { scanf("%d",&dist[i][j]); if(dist[i][j]==0) dist[i][j]=inf; } } floyd(); int l=0,r=10000; while(l<r) { int mid=(l+r)/2; buildmap(mid); int xx=dinic(); if(xx>=c) { r=mid; } else { l=mid+1; } } printf("%d ",r); }