题意:给出N,C,M,N是挤奶器的数量,C是奶牛的数量,M是每个挤奶器最多给多少只奶牛使用。
给出一个(N+C) * (N+C)的矩阵,代表挤奶器和奶牛之间的距离,0代表无法到达,这个坑了我好久。
问:如何在满足最大流的情况下使某个奶牛走的最长距离最短。
思路:先跑一边floyd,dis[][] = 0 ,无法到达,所以需要特判,这里WA了5 6 次。
二分边的长度,每次建一次图,满足小于等于这个边长的可以相连,然后跑一次dinic,看最大流是否等于奶牛的数量。
S - 挤奶器 ,权值是M,反向为0。
挤奶器 -奶牛,权值是1,反向为0。
奶牛 - T ,权值是1,反向为0。
具体见代码。
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <map> using namespace std; #define Max 250 #define mem(a,b) memset(a,b,sizeof(a)) int N,M,C; int Map[Max][Max] ; #define inf 1 << 30 #include <cstring> #include <string> struct kdq { int s , e , l ,next ; } ed[Max * 100] ; int head[Max] ,num ; int S,T ; void add(int s ,int e ,int l ) { ed[num].s = s ; ed[num].e = e ; ed[num].l = l ; ed[num].next = head[s] ; head[s] = num ++ ; ed[num].s = e ; ed[num].e = s ; ed[num].l = 0 ; ed[num].next = head[e] ; head[e] = num ++ ; } void init() { mem(head,-1) ; num = 0 ; } int deep[Max] ; int qe[Max * 100] ; int dinic_bfs() { mem(deep,-1) ; deep[S] = 0 ; int h = 0 ,t = 0 ; qe[h ++ ] = S ; while(h > t) { int tt = qe[t ++ ] ; for (int i = head[tt] ; ~i ; i = ed[i].next ) { int e = ed[i].e ; int l = ed[i].l ; if(deep[e] == -1 && l > 0 ) { deep[e] = deep[tt] + 1 ; qe[h ++ ] = e ; } } } return deep[T] != -1 ; } int dinic_dfs(int now ,int f ) { if(now == T)return f ; int flow = 0 ; for (int i = head[now] ; ~i ; i = ed[i].next ) { int e = ed[i].e ; int l = ed[i].l ; if(deep[e] == deep[now] + 1 && l > 0) { int mm = min(l,f - flow) ; int nn = dinic_dfs(e , mm) ; flow += nn ; ed[i].l -= nn ; ed[i ^ 1].l += nn ; } } if(!flow )deep[now] = -2 ; return flow ; } int dinic() { int flow = 0 ; while(dinic_bfs()) { flow += dinic_dfs(S,inf) ; } return flow ; } void floyd() { for (int k = 1 ; k <= N + C ; k ++ ) { for (int i = 1 ; i <= N + C ; i ++ ) { if(Map[i][k] == inf)continue ;//无法到达 for (int j = 1 ; j <= N + C ; j ++) { if(Map[j][k] == inf) continue ;//无法到达 if(Map[i][k] + Map[k][j] < Map[i][j])Map[i][j] = Map[i][k] + Map[k][j] ; } } } } void build_Map(int mid) { S = 0 ,T = N + C + 1 ; init() ; for (int i = 1 ; i <= N ; i ++) { for (int j = N + 1 ; j <= N + C ; j ++) { if(Map[i][j] <= mid) { add(i,j,1) ; } } } for (int i = N + 1 ; i <= N + C ; i ++)add(i,T,1) ; for (int i = 1 ; i <= N ; i ++ )add(S,i,M) ; } int main() { while(scanf("%d%d%d",&N,&C,&M) != EOF) { for (int i = 1 ; i <= N + C ; i ++ ) for (int j = 1 ; j <= N + C ; j ++ ) { scanf("%d",&Map[i][j]) ; if(!Map[i][j])Map[i][j] = inf ; } floyd() ; int l = 0 ,r = 100000 ; int mid = l + r >> 1 ; while(r > l) { mid = (l + r ) / 2 ; build_Map(mid) ; int ans = dinic() ; if(ans < C) l = mid + 1 ; else r = mid ; } cout << r <<endl; } return 0; }