题意:
K太机器,C头牛,之间有距离,每个机器能供m头牛,没头牛需要一台机器。问在所有牛都有机器供应,并且牛离机器距离的最大距离最小是多少。
题解:
二分枚举最大距离,然后网络流建边,满足不大于枚举的最大距离才能建边.
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #define B(x) (1<<(x)) using namespace std; typedef long long ll; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } void cmax(ll& a,ll b){ if(b>a)a=b; } void cmin(ll& a,ll b){ if(b<a)a=b; } void add(int& a,int b,int mod){ a=(a+b)%mod; } void add(ll& a,ll b,ll mod){ a=(a+b)%mod; } const int oo=0x3f3f3f3f; const int MOD=1000000007; const int maxn=1000; const int maxm=900000; struct EDGE{ int v,next,c,f; }E[maxm]; int head[maxn],tol; int gap[maxn],dep[maxn],pre[maxn],cur[maxn]; int dis[500][500]; int K,C,M; void Init(){ memset(head,-1,sizeof head); tol=0; } void add_edge(int u,int v,int f,int rf=0){ E[tol].v=v; E[tol].c=f; E[tol].f=0; E[tol].next=head[u]; head[u]=tol++; E[tol].v=u; E[tol].c=rf; E[tol].f=0; E[tol].next=head[v]; head[v]=tol++; } int isap(int start,int end,int N){ memset(gap,0,sizeof gap); memset(dep,0,sizeof dep); memcpy(cur,head,sizeof head); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start]<N){ if(u==end){ int Min=oo; for(int i=pre[u];i!=-1;i=pre[E[i^1].v]) if(Min>E[i].c-E[i].f) Min=E[i].c-E[i].f; for(int i=pre[u];i!=-1;i=pre[E[i^1].v]){ E[i].f+=Min; E[i^1].f-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];i!=-1;i=E[i].next){ v=E[i].v; if(E[i].c-E[i].f&&dep[v]+1==dep[u]){ flag=true; cur[u]=pre[v]=i; break; } } if(flag){ u=v; continue; } int Min=N; for(int i=head[u];i!=-1;i=E[i].next) if(E[i].c-E[i].f&&dep[E[i].v]<Min){ Min=dep[E[i].v]; cur[u]=i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start)u=E[pre[u]^1].v; } return ans; } bool ok(int maxl){ int s=K+C+1,t=s+1; for(int i=1;i<=K;i++)add_edge(s,i,M); for(int i=K+1;i<=K+C;i++)add_edge(i,t,1); for(int i=1;i<=K;i++) for(int j=K+1;j<=K+C;j++) if(dis[i][j]<=maxl) add_edge(i,j,1); return isap(s,t,t)==C; } void floyd(){ for(int k=1;k<=K+C;k++){ for(int i=1;i<=K+C;i++){ for(int j=1;j<=K+C;j++){ if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j]; } } } } int main(){ //freopen("E:\\read.txt","r",stdin); while(scanf("%d %d %d",&K,&C,&M)){ int l=0,r=0; for(int i=1;i<=K+C;i++) for(int j=1;j<=K+C;j++) scanf("%d",&dis[i][j]); floyd(); Init(); for(int i=1;i<=K+C;i++) for(int j=1;j<=K+C;j++) cmax(r,dis[i][j]); while(l<=r){ int mid=(l+r)>>1; if(ok(mid)) r=mid-1; else l=mid+1; } printf("%d\n",l); } return 0; }