博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 2391.Ombrophobic Bovines (最大流)
阅读量:5937 次
发布时间:2019-06-19

本文共 3698 字,大约阅读时间需要 12 分钟。

实际上是求最短的避雨时间。

首先将每个点拆成两个,一个连接源点,一个连接汇点,连接源点的点的容量为当前单的奶牛数,连接汇点的点为能容纳的奶牛数。

floyd求任意两点互相到达的最短时间,二分最长时间,最大流判断是否可行。

注意路径时间会超过int

 

/*      最大流SAP      邻接表      思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧。      优化:      1、当前弧优化(重要)。      1、每找到以条增广路回退到断点(常数优化)。      2、层次出现断层,无法得到新流(重要)。      时间复杂度(m*n^2)*/#include 
#include
#include
#define ms(a,b) memset(a,b,sizeof a)using namespace std;const int INF = 500;long long G[INF][INF];struct node { int v, c, next;} edge[INF*INF * 4];long long pHead[INF*INF], SS, ST, nCnt;void addEdge (int u, int v, int c) { edge[++nCnt].v = v; edge[nCnt].c = c, edge[nCnt].next = pHead[u]; pHead[u] = nCnt; edge[++nCnt].v = u; edge[nCnt].c = 0, edge[nCnt].next = pHead[v]; pHead[v] = nCnt;}int SAP (int pStart, int pEnd, int N) { int numh[INF], h[INF], curEdge[INF], pre[INF]; int cur_flow, flow_ans = 0, u, neck, i, tmp; ms (h, 0); ms (numh, 0); ms (pre, -1); for (i = 0; i <= N; i++) curEdge[i] = pHead[i]; numh[0] = N; u = pStart; while (h[pStart] <= N) { if (u == pEnd) { cur_flow = 1e9; for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) if (cur_flow > edge[curEdge[i]].c) neck = i, cur_flow = edge[curEdge[i]].c; for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) { tmp = curEdge[i]; edge[tmp].c -= cur_flow, edge[tmp ^ 1].c += cur_flow; } flow_ans += cur_flow; u = neck; } for ( i = curEdge[u]; i != 0; i = edge[i].next) if (edge[i].c && h[u] == h[edge[i].v] + 1) break; if (i != 0) { curEdge[u] = i, pre[edge[i].v] = u; u = edge[i].v; } else { if (0 == --numh[h[u]]) continue; curEdge[u] = pHead[u]; for (tmp = N, i = pHead[u]; i != 0; i = edge[i].next) if (edge[i].c) tmp = min (tmp, h[edge[i].v]); h[u] = tmp + 1; ++numh[h[u]]; if (u != pStart) u = pre[u]; } } return flow_ans;}long long m, n, x, y,sum,c;int in[INF], out[INF];bool check (long long tem) { nCnt = 1; SS = 2 * n + 1, ST = 2 * n + 2; memset (pHead, 0, sizeof pHead); for (int i = 1; i <= n; i++) { if(out[i]) addEdge (SS, i, out[i]); for (int j =1; j <= n; j++) if (G[i][j] <= tem&&G[i][j]!=-1) addEdge (i, j+n, 5000); } for (int i = 1; i <= n; i++) if(in[i])addEdge (i + n, ST, in[i]); int ans = SAP (SS, ST, ST); if (ans == sum) return 1; return 0;}int main() { /* 建图,前向星存边,表头在pHead[],边计数 nCnt. SS,ST分别为源点和汇点 */ ms (G, -1); cin>>n>>m; for (int i = 1; i <= n; i++) { cin>>out[i]>>in[i]; sum += out[i]; } long long l = 0x7fffffffffffffff, r = 0; for (int i = 1; i <= n; i++) G[i][i] = 0; for (int i = 1; i <= m; i++) { cin>>x>>y>>c; if(G[x][y]>0) G[x][y] = G[y][x] = min(c,G[x][y]); else G[x][y]=G[y][x]=c; l = min (l, c), r = max (r, c); } for (int t = 1; t <= n; t++) for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { if (G[i][t] == -1 || G[t][j] == -1) continue; if (G[i][j] == -1 || G[i][j] > G[i][t] + G[t][j]) G[i][j] = G[i][t] + G[t][j], l = min (l, G[i][j]), r = max (r, G[i][j]); } long long last = -1,mid; while (l <= r) { mid = (l + r) >> 1; if (check (mid) ) { last = mid; r = mid - 1; } else l = mid + 1; } cout<
View Code

 

转载于:https://www.cnblogs.com/keam37/p/3973941.html

你可能感兴趣的文章
20款精美的精品电子商务设计~值得一看哦
查看>>
阿里云云服务器上安装Apache
查看>>
试用阿里云邮件推送服务
查看>>
Extra Credits: Easy Games 17
查看>>
Linux组件封装(八)——Socket的封装
查看>>
展开字符串
查看>>
关于选择器(很早之前写的)
查看>>
android 下linux的I2C 读写函数实例
查看>>
CLI组成
查看>>
maven - Eclipse构建maven项目
查看>>
关于VS2008/2010中SORT,stable_sort的比较函数中strict weak ordering
查看>>
局部内部类
查看>>
apache 开启网页压缩功能
查看>>
[Android四大组件之一]——Activity
查看>>
使用 ButterKnife 操作无效(不报错、点击后没效果)------代码编写错误
查看>>
Test of String
查看>>
[转载]Linux内存高,触发oom-killer问题解决
查看>>
SqlServer中的merge操作(转载)
查看>>
学习进度条(第十四周)
查看>>
工控随笔_C#连接PLC_之_C#入门_01_配置学习环境
查看>>