题意:给一堆点,一部分是牛,一部分是机器,每头牛必须要走到一个机器,每个点之间有距离,要求每头牛都能找得到一台机器(机器有最大容量)的情况下,走的最远的牛距离最小
题解:二分答案,小于该距离的边才能加进来,先用floyd预处理距离,然后跑最大流看满不满足条件
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-12; const int N=400+10,maxn=100000+10,inf=0x3f3f3f3f; struct edge{ int to,Next,c; }e[maxn<<2]; int cnt,head[N]; int dis[N]; int d[N][N]; void add(int u,int v,int c) { // cout<<u<<" "<<v<<" "<<c<<endl; e[cnt].to=v; e[cnt].c=c; e[cnt].Next=head[u]; head[u]=cnt++; e[cnt].to=u; e[cnt].c=0; e[cnt].Next=head[v]; head[v]=cnt++; } bool bfs(int s,int t) { memset(dis,-1,sizeof dis); dis[s]=0; queue<int>q; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); if(x==t)return 1; for(int i=head[x];~i;i=e[i].Next) { int te=e[i].to; if(dis[te]==-1&&e[i].c>0) { dis[te]=dis[x]+1; q.push(te); } } } return 0; } int dfs(int x,int mx,int t) { if(x==t)return mx; int flow=0; for(int i=head[x];~i;i=e[i].Next) { int te=e[i].to,f; if(e[i].c>0&&dis[te]==dis[x]+1&&(f=dfs(te,min(mx-flow,e[i].c),t))) { e[i].c-=f; e[i^1].c+=f; flow+=f; } } if(!flow)dis[x]=-2; return flow; } int maxflow(int s,int t) { int ans=0,f; while(bfs(s,t)) { while((f=dfs(s,inf,t)))ans+=f; } return ans; } void init() { cnt=0; memset(head,-1,sizeof head); } int n,m,k; bool ok(int x,int s,int t) { init(); for(int i=1+n;i<=n+m;i++)add(s,i,1); for(int i=1;i<=n;i++)add(i,t,k); for(int i=1+n;i<=n+m;i++) for(int j=1;j<=n;j++) if(d[i][j]<=x) add(i,j,d[i][j]); return maxflow(s,t)>=m; } int main() { while(~scanf("%d%d%d",&n,&m,&k)) { memset(d,inf,sizeof d); for(int i=1;i<=n+m;i++)d[i][i]=0; for(int i=1;i<=n+m;i++) { for(int j=1;j<=n+m;j++) { int x; scanf("%d",&x); if(x)d[i][j]=x; } } for(int i=1;i<=n+m;i++) for(int j=1;j<= n+m;j++) for(int k=1;k<=n+m;k++) d[j][k]=min(d[j][k],d[j][i]+d[i][k]); /* for(int i=1+n;i<=n+m;i++) { for(int j=1;j<=n;j++) cout<<d[i][j]<<" "; cout<<endl; }*/ int s=n+m+1,t=n+m+2; int l=0,r=inf; while(r-l>1) { int m=(l+r)/2; if(ok(m,s,t))r=m; else l=m; } printf("%d ",r); } return 0; } /******************** ********************/