Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 9624 | Accepted: 3474 | |
Case Time Limit: 1000MS |
Description
Input
Output
Sample Input
2 3 2 0 3 2 1 1 3 0 3 2 0 2 3 0 1 0 1 2 1 0 2 1 0 0 2 0
Sample Output
2
思路:首先用floyd求出奶牛和挤奶器之间的最短距离,然后二分枚举最长距离(maxdist),若奶牛和挤奶器之间的距离小于或等于maxdist,则建一条边,边容量为1;对于每一头奶牛i,建一条边s->i,边容量为1;对于每一台挤奶器i,建一条边i->t,边容量为M。
#include<iostream> #include<cstdio> using namespace std; const int MAXN=300; const int INF=(1<<29); int dis[MAXN][MAXN];//任意两点的最短距离 int flow[MAXN][MAXN];//容量限制 int level[MAXN];//分层 int K,C,M; int n; void floyd() { int i,j,k; for(i=1;i<=n;i++) for(j=1;j<=n;j++) for(k=1;k<=n;k++) dis[j][k]=min(dis[j][i]+dis[i][k],dis[j][k]); } void build(int max) { int i,j; for(i=0;i<=n+1;i++) for(j=0;j<=n+1;j++) flow[i][j]=flow[j][i]=0; for(i=K+1;i<=n;i++) flow[0][i]=1; for(i=1;i<=K;i++) flow[i][n+1]=M; for(i=K+1;i<=n;i++) for(j=1;j<=K;j++) if(dis[i][j]<=max) flow[i][j]=1; } int bfs() { int queue[MAXN],front,rear; for(int i=0;i<=n+1;i++) level[i]=0; level[0]=1; front=rear=0; queue[rear++]=0; while(front!=rear) { int v=queue[front++]; for(int i=0;i<=n+1;i++) if(!level[i]&&flow[v][i]) { level[i]=level[v]+1; queue[rear++]=i; } } return level[n+1]; } int find(int u,int f) { if(u==n+1) return f; int t,sum; sum=0; for(int i=0;i<=n+1;i++) { if(f&&flow[u][i]&&level[u]+1==level[i]) { int t=find(i,min(f,flow[u][i])); flow[u][i]-=t; flow[i][u]+=t; f-=t; sum+=t; } } return sum; } int dinic() { int maxflow; int low,mid,up; low=0; up=100000; while(low<=up) { mid=(low+up)>>1; build(mid); maxflow=0; while(bfs()) maxflow+=find(0,INF); if(maxflow<C) low=mid+1; else up=mid-1; } return up+1; } int main() { int i,j; while(~scanf("%d%d%d",&K,&C,&M)) { n=K+C; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&dis[i][j]); if(dis[i][j]==0) dis[i][j]=INF; } floyd(); printf("%d\n",dinic()); } return 0; }