POJ 2391 二分,Floyd, 网络最大流
来源:互联网 发布:管理类联考网络冲刺班 编辑:程序博客网 时间:2024/05/22 03:45
题目链接:http://poj.org/problem?id=2391
题意:
有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 <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1010;const int maxm = 510010;const int inf = 0x3f3f3f3f;const long long INF = 0x7F7F7F7F7F7F7F;struct G{ int v, cap, next; G() {} G(int v, int cap, int next) : v(v), cap(cap), next(next) {}} E[maxm];int p[maxn], T;int d[maxn], temp_p[maxn], qw[maxn]; //d顶点到源点的距离标号,temp_p当前狐优化,qw队列void init(){ memset(p, -1, sizeof(p)); T = 0;}void add(int u, int v, int cap){ E[T] = G(v, cap, p[u]); p[u] = T++; E[T] = G(u, 0, p[v]); p[v] = T++;}bool bfs(int st, int en, int n){ int i, u, v, head, tail; for(i = 0; i <= n; i++) d[i] = -1; head = tail = 0; d[st] = 0; qw[tail] = st; while(head <= tail) { u = qw[head++]; for(i = p[u]; i + 1; i = E[i].next) { v = E[i].v; if(d[v] == -1 && E[i].cap > 0) { d[v] = d[u] + 1; qw[++tail] = v; } } } return (d[en] != -1);}int dfs(int u, int en, int f){ if(u == en || f == 0) return f; int flow = 0, temp; for(; temp_p[u] + 1; temp_p[u] = E[temp_p[u]].next) { G& e = E[temp_p[u]]; if(d[u] + 1 == d[e.v]) { temp = dfs(e.v, en, min(f, e.cap)); if(temp > 0) { e.cap -= temp; E[temp_p[u] ^ 1].cap += temp; flow += temp; f -= temp; if(f == 0) break; } } } return flow;}int dinic(int st, int en, int n){ int i, ans = 0; while(bfs(st, en, n)) { for(i = 0; i <= n; i++) temp_p[i] = p[i]; ans += dfs(st, en, inf); } return ans;}int n, m, sum;long long g[1005][1005];int have[1005], hold[1005];bool check(long long t){ init(); for(int i=1; i<=n; i++){ add(0, i, have[i]); add(i+n, 2*n+1, hold[i]); add(i, i+n, inf); } for(int i=1; i<=n; i++){ for(int j=i+1; j<=n; j++){ if(g[i][j]<=t){ add(i,j+n, inf); add(j, i+n, inf); } } } int ans = dinic(0,2*n+1,2*n+2); return ans >= sum;}int main(){ while(~scanf("%d%d", &n, &m)){ sum = 0; for(int i=1; i<=n; i++){ scanf("%d%d", &have[i],&hold[i]); sum+=have[i]; } for(int i = 1; i <= n; i++){ for(int j = 1; j<=n; j++){ g[i][j] = INF; } } for(int i=1; i<=n; i++) g[i][i]=0; for(int i=1; i<=m; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); if(g[u][v] > w){ g[u][v] = g[v][u] = w; } } for(int k=1;k<=n;k++){ for(int i=1; i<=n; i++){ for(int j=1; j<=n; j++){ if(g[i][k]!=INF&&g[k][j]!=INF&&g[i][j]>g[i][k]+g[k][j]){ g[i][j] = g[i][k] + g[k][j]; } } } } long long ans = -1, l = 0, r = 10000000000000LL; while(l <= r){ long long mid = (l+r)/2; if(check(mid)) ans = mid, r = mid-1; else l = mid+1; } printf("%lld\n", ans); } return 0;}
0 0
- POJ 2391 二分,Floyd, 网络最大流
- POJ 2391 - Ombrophobic Bovines(网络流’最大流+Floyd+二分)
- POJ 2391 floyd+二分+最大流
- poj 2391 floyd+二分+最大流
- poj 2391 (Floyd+最大流+二分)
- POJ 2391 floyd+二分最大流
- POJ 2112 2391 floyd 二分 最大流
- POJ 2391-Ombrophobic Bovines(网络流_最大流+floyd+二分)
- POJ--2391--Ombrophobic Bovines【拆点+Floyd+Dinic优化+二分答案】网络最大流
- poj 2391 Ombrophobic Bovines(floyd+二分+最大流)
- POJ 2391 - Ombrophobic Bovines Floyd+二分+加点构图最大流.
- POJ 2391 Ombrophobic Bovines(二分+floyd+最大流)
- poj 2391 最大流+floyd+二分(转移避难)
- POJ 2391 最大流 二分 拆点 floyd
- POJ 2391 —— Ombrophobic Bovines 二分+Floyd+最大流
- poj 2391 Ombrophobic Bovines(floyd+二分+最大流)
- POJ 2391 Floyd+二分+拆点最大流
- POJ 2391 Ombrophobic Bovines(二分+floyd+最大流)
- C++ 多继承和虚继承的内存布局
- linux下nfs配置
- myeclipse最常用的快捷键
- 欢迎使用CSDN-markdown编辑器
- Android开源库和项目
- POJ 2391 二分,Floyd, 网络最大流
- BeautifulSoup模块学习
- hdu1269迷宫城堡
- 神经网络浅讲:从神经元到深度学习
- 将本地项目上传至GitHub上
- bzoj 3160: 万径人踪灭 (FFT+manacher)
- Spring 核心技术——IoC 之 DI (2)
- 经典查找算法 --- B+树
- hdu--1045--Fire Net,NYOJ--587--dfs--blockhouses