标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16460 | Accepted: 3593 |
Description
Input
Output
Sample Input
3 4 7 2 0 4 2 6 1 2 40 3 2 70 2 3 90 1 3 120
Sample Output
110
Hint
有n个田地,给出每个田地上初始的牛的数量和每个田地可以容纳的牛的数量。
m条双向的路径,每条路径上可以同时通过的牛没有限制。
问牛要怎么走,能在最短时间内使得每块田地都能容纳的下,输出最短时间或-1。
先floyd求出任意两点之间的最短距离,然后二分答案,判断是否可以在时间不超过mid的情况下完成移动:
建图:
每个点拆成两个点 x 和 x‘,源点向 x 连边,权值为初始的牛的数量;
x‘向汇点连边,权值为可以容纳的牛的数量;
x向x‘连边,权值为INF。
然后枚举任意两点i和j,如果i和j之间的最短距离dist[i][j]<=mid,则建边i->j‘,权值为INF。
此时计算最大流,就是在限定mid时间内可以移动的最多的牛的数量,如果大于等于牛的总数则说明可行,否则不可行。继续二分。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #define maxn 600 #define maxm 1000000 #define INF 1000000000 + 1000 #define INF1 1e16 using namespace std; struct node { int u, v, cap, flow, next; }; node edge[maxm]; long long map[maxn][maxn]; int head[maxn], cur[maxn], cnt; int dist[maxn], vis[maxn]; int all[maxn], can[maxn]; int F, P, sum; void init(){ cnt = 0; memset(head, -1, sizeof(head)); } void add(int u, int v, int w){ edge[cnt] = {u, v, w, 0, head[u]}; head[u] = cnt++; edge[cnt] = {v, u, 0, 0, head[v]}; head[v] = cnt++; } void floy(){ int i, j, k; for(k = 1; k <= F; ++k) for(i = 1; i <= F; ++i){ if(map[i][k] != INF1) for(j = 1; j <= F; ++j) map[i][j] = min(map[i][k] + map[k][j], map[i][j]); } } void getmap(long long min_max){ for(int i = 1; i <= F; ++i){ add(0, i, all[i]); //0 为源点 add(i + F, 2 * F + 1, can[i]); //2 * F + 1 为汇点 } for(int i = 1; i <= F; ++i) for(int j = 1; j <= F; ++j) if(map[i][j] <= min_max) add(i, j + F, INF); } bool BFS(int st, int ed){ queue<int>q; memset(vis, 0, sizeof(vis)); memset(dist, -1, sizeof(dist)); q.push(st); vis[st] = 1; dist[st] = 0; while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edge[i].next){ node E = edge[i]; if(!vis[E.v] && E.cap > E.flow){ vis[E.v] = 1; dist[E.v] = dist[u] + 1; if(E.v == ed) return true; q.push(E.v); } } } return false; } int DFS(int x, int ed, int a){ if(a == 0 || x == ed) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i =edge[i].next){ node &E = edge[i]; if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow))) > 0){ E.flow += f; edge[i ^ 1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int maxflow (int st, int ed){ int flowsum = 0; while(BFS(st, ed)){ memcpy(cur, head, sizeof(head)); flowsum += DFS(st, ed, INF); } return flowsum; } int main (){ while(scanf("%d%d", &F, &P) != EOF){ sum = 0; for(int i = 1; i <= F; ++i){ scanf("%d%d", &all[i], &can[i]); sum += all[i]; } for(int i = 1; i <= F; ++i) for(int j = 1; j <= F; ++j){ if(i == j) map[i][j] = 0; else map[i][j] = map[j][i] = INF1; } int u ,v, w; for(int i = 1; i <= P; ++i){ scanf("%d%d%d", &u, &v, &w); if(map[u][v] > w) map[u][v] = map[v][u] = w; } floy(); long long r = INF1; long long l = 0; long long mid, ans; long long num = -1; while(r > l){ mid = (l + r) / 2; ans = 0; init(); getmap(mid); ans = maxflow(0, 2 * F + 1); if(ans >= sum) { r = mid; num = mid; } else l = mid + 1; } printf("%lld\n", num); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ 2391--Ombrophobic Bovines【拆点 && 二分 && 最大流dinic && 经典】
标签:
原文地址:http://blog.csdn.net/hpuhjh/article/details/47320181