POJ 2112 Optimal Milking【二分+最大流】
2015-09-09 21:22
489 查看
题目链接:http://poj.org/problem?id=2112
最小化最大流量边。
建图:源点向机器建边,容量为m,牛向汇点建边,容量1,机器与牛之间建边(若符合条件),容量1。
代码:
最小化最大流量边。
建图:源点向机器建边,容量为m,牛向汇点建边,容量1,机器与牛之间建边(若符合条件),容量1。
代码:
[code]#include <iostream> #include <algorithm> #include <set> #include <map> #include <string.h> #include <queue> #include <sstream> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string> using namespace std; const int MAXN = 101000;//点数的最大值 const int MAXM = 400100;//边数的最大值 const int INF = 0x3f3f3f3f; struct Edge { int to, next, cap, flow; }edge[MAXM];//注意是MAXM int tol; int head[MAXN]; int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN]; void init() { tol = 0; memset(head, -1, sizeof(head)); } //加边,单向图三个参数,双向图四个参数 void addedge(int u, int v, int w, int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].next = head[u]; edge[tol].flow = 0; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].next = head[v]; edge[tol].flow = 0; head[v] = tol++; } //输入参数:起点、终点、点的总数 //点的编号没有影响,只要输入点的总数 int Q[MAXN]; void BFS(int start, int end) { memset(dep, -1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while (front != rear) { int u = Q[front++]; for (int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if (dep[v] != -1) continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int sap(int start, int end, int N) { BFS(start, end); memcpy(cur, head, sizeof(head)); int u = start; int top = 0; int ans = 0; while (dep[start] < N) { if (u == end) { int Min = INF; int inser; for (int i = 0; i < top; i++) if (Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for (int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i] ^ 1].flow -= Min; } ans += Min; top = inser; u = edge[S[top] ^ 1].to; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]) { flag = true; cur[u] = i; break; } } if (flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if (u != start) u = edge[S[--top] ^ 1].to; } return ans; } int k, c, m; int a[2345][2345]; int main() { while (~scanf("%d%d%d", &k, &c, &m)) { memset(a, 0, sizeof(a)); int n = k + c; for (int i = 1;i <= n;i++) for (int j = 1;j <= n;j++) { scanf("%d", &a[i][j]); if (a[i][j] == 0) a[i][j] = 1e6; } //预处理最短距离 for (int p = 1;p <= n;p++) for (int i = 1;i <= n;i++) for (int j = 1;j <= n;j++) a[i][j] = min(a[i][j], a[i][p] + a[p][j]); int left = 0, right = 1000000; int ans = 1000000; while (left <= right) { init(); for (int i = 1;i <= k;i++) addedge(0, i, m); for (int i = k + 1;i <= k + c;i++) addedge(i, k + c + 1, 1); int mid = (left + right) / 2; for (int i = 1;i <= k;i++) for (int j = k + 1;j <= n;j++) { if (a[i][j] <= mid) addedge(i, j, 1); } if (sap(0, k + c + 1, k + c + 2) == c) { right = mid - 1; ans = min(mid, ans); } else left = mid + 1; } printf("%d\n", ans); } return 0; }
相关文章推荐
- wr703n路由器搭载openwrt系统挂载U盘历程
- linux 初级阶段整理笔记
- 网站添加favicon.ico图标
- centos 下面安装lamp
- mac install tomcat8
- Linux(Ubuntu-GNOME)桌面常用快捷方式总结
- 浅谈Linux文件系统
- linux磁盘分区fdisk命令详解
- Hadoop学习笔记六之 URLClassLoader && ConnectionRefused 异常
- tomcat server.xml配置介绍
- qrencode二维码生成在linux下的编译(转)
- Linux 文件查看常用命令
- linux文件查找命令
- 第一天:探索(2)
- Linux2.6.32内核笔记(2)内存管理子系统
- AIX和Linux如何确认磁盘是本地还是存储上的
- Linux运维之路第一部总结及扩展
- Shell笔记
- linux /sbin FHS翻译
- shell脚本操作mysql数据库 (部份参考)