POJ 2112 最大流 最短路
阿新 • • 發佈:2019-02-25
|| can truct std ifd nic ini bfs 奶牛
POJ 2112 最大流 最短路
題意:給定K個擠奶器和C頭奶牛,每個擠奶器每天最多擠m頭奶牛;擠奶器和奶牛稱為“實物”,再給每個實物之間的距離。問擠完所有奶牛,奶牛所需走最短的距離。
分析:用Floyd求出“實物”之間的最短距離,求最大流,二分找最短距離。
#include <queue> #include <cstring> #include <cstdio> using namespace std; const int N = 250; int K, C, n, m, cnt, st, ed; struct node{ int v, w, nxt; }edge[N * N]; int e[N][N], fir[N], deep[N]; inline void add(int u, int v, int w){ edge[++cnt] = (node){v, w, fir[u]}; fir[u] = cnt; edge[++cnt] = (node){u, 0, fir[v]}; fir[v] = cnt; } inline int bfs(){ memset(deep, 0, sizeof(deep)); deep[st] = 1; queue<int> q; q.push(st); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = fir[u]; i; i = edge[i].nxt){ int v = edge[i].v; if(edge[i].w && !deep[v]){ deep[v] = deep[u] + 1; q.push(v); } } } return deep[ed]; } inline int dfs(int u, int fl){ if(u == ed || fl == 0) return fl; int f = 0; for(int i = fir[u]; i; i = edge[i].nxt){ int v = edge[i].v; if(edge[i].w && deep[u] + 1 == deep[v]){ int x = dfs(v, min(fl, edge[i].w)); edge[i].w -= x; edge[i^1].w += x; fl -= x; f += x; } } if(!f) deep[u] = -2; return f; } inline int Dinic(){ int ans = 0, d; while(bfs()){ while((d = dfs(st, 0x3f3f3f3f))){ ans += d; } } return ans; } inline void Floyd(){ for(int k = 1; k <= n; k++){ for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ if(e[i][j] > e[k][i] + e[j][k]){ e[i][j] = e[k][i] + e[j][k]; } } } } } inline void built(int mid){ cnt = 1; memset(fir, 0, sizeof(fir)); for(int i = K + 1; i <= n; i++) add(st, i, 1);//源點到每個奶牛 for(int i = 1; i <= K; i++) add(i, ed, m);//擠奶器到匯點 for(int i = 1; i <= K; i++){ for(int j = K + 1; j <= n; j++){ if(e[i][j] <= mid) add(j, i, 1);//奶牛到擠奶器的距離小於mid,就加一條容量為1的邊。 } } } int main(){ #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); #endif //ONLINE_JUDGE while(~scanf("%d%d%d", &K, &C, &m)){ n = K + C; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ scanf("%d", &e[i][j]); if(i != j && !e[i][j]) e[i][j] = 0x3f3f3f3f; } } Floyd(); int l = 0, r = 0x3f3f3f3f; st = 0, ed = n + 1; while(l <= r){ int mid = (l + r) / 2; built(mid); int ans = Dinic(); if(ans == C) r = mid - 1;//如果滿足就縮小上限 else l = mid + 1; } printf("%d\n", r + 1); } return 0; }
POJ 2112 最大流 最短路