SCU2016-01 G题(最大流 + floyd_warshall)
来源:互联网 发布:php程序设计是做什么的 编辑:程序博客网 时间:2024/04/29 19:05
分析:
其实就是经典的限制终点的容量的最大流。建立超级源点和汇点。最小化最大路径,二分一下。对于任意最短路Floyd_warshall一下。
code:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <queue>using namespace std;#define pr(x) cout << #x << ": " << x << " " #define pl(x) cout << #x << ": " << x << endl;const int INF = int(1e9);////////////////////////最大流开始//////////////////////////////////////typedef int cap_type;#define MAX_V 200 + 30 + 16// 用于表示边的结构体(终点、容量、反向边)struct edge{ int to, rev; cap_type cap; edge(int to, cap_type cap, int rev) : to(to), cap(cap), rev(rev) {}};vector <edge> G[MAX_V]; // 图的邻接表表示int level[MAX_V]; // 顶点到源点的距离标号int iter[MAX_V]; // 当前弧,在其之前的边已经没有用了// 向图中加入一条从from到to的容量为cap的边void add_edge(int from, int to, int cap){ G[from].push_back(edge(to, cap, G[to].size())); G[to].push_back(edge(from, 0, G[from].size() - 1));}// 通过BFS计算从源点出发的距离标号void bfs(int s){ memset(level, -1, sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while (!que.empty()) { int v = que.front(); que.pop(); for (int i = 0; i < (int)G[v].size(); ++i) { edge &e = G[v][i]; if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; que.push(e.to); } } }}// 通过DFS寻找增广路cap_type dfs(int v, int t, cap_type f){ if (v == t) { return f; } for (int &i = iter[v]; i < (int)G[v].size(); ++i) { edge &e = G[v][i]; if (e.cap > 0 && level[v] < level[e.to]) { cap_type d = dfs(e.to, t, min(f, e.cap)); if (d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0;}// 求解从s到t的最大流cap_type max_flow(int s, int t){ cap_type flow = 0; for (;;) { bfs(s); if (level[t] < 0) { return flow; } memset(iter, 0, sizeof(iter)); cap_type f; while ((f = dfs(s, t, 0x3f3f3f3f) > 0)) { flow += f; } }}///////////////////////////////最大流结束/////////////////////////////////////struct jibancanyang{ int K, C, M, Ga[234][234]; void floyd_warshall() { for (int i = 0; i < K + C; ++i) { for (int j = 0; j < K + C; ++j) { for (int k = 0; k < K + C; ++k) { Ga[j][k] = min(Ga[j][i] + Ga[i][k], Ga[j][k]); } } } } bool judge(int mid) { int s = C + K, t = s + 1; for (int i = 0; i <= t; ++i) G[i].clear(); for (int i = 0; i < K; ++i) add_edge(i, t, M); for (int i = K; i < K + C; ++i) add_edge(s, i, 1); for (int i = 0; i < K; ++i) { for (int j = K; j < K + C; ++j) { if (Ga[i][j] <= mid) add_edge(j, i, 1); } } return max_flow(s, t) == C; } int binary_search() { floyd_warshall(); int l = 0, r = 200 * (K + C); while (l < r) { int mid = (r - l) / 2 + l; if (judge(mid)) r = mid; else l = mid + 1; } return l; } void fun() { scanf("%d%d%d", &K, &C, &M); for (int i = 0; i < K + C; ++i) { for (int j = 0; j < K + C; ++j) { scanf("%d", &Ga[i][j]); Ga[i][j] = Ga[i][j] ? Ga[i][j] : INF; } } printf("%d\n", binary_search()); }}ac;int main(){#ifdef LOCAL freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);#endif ac.fun(); return 0;}
0 0
- SCU2016-01 G题(最大流 + floyd_warshall)
- SCU2016-02 G题 (技巧)
- SCU2016-01 M题
- SCU2016-05 G题双重二分
- SCU2016-04 G题 01trie树第k大,树上异或路径
- SCU2016-01 E题 贪心
- SCU2016-01 H题 (二分图带权匹配 KM算法)
- SCU2016-01 J 题 欧拉路径
- SCU2016-02 A题(LCA)
- SCU2016-02 M题 (dp)
- SCU2016-02 P题 (凸包)
- SCU2016-02 I题 (反转技巧)
- SCU2016-02 J题 (开关反转)
- SCU2016-02 T题 (LIS)
- SCU2016-04 F题 (大模拟)
- SCU2016-05 K题 (模拟水)
- SCU2016-01 F贪心
- SCU2016-01 N dijkstra
- 知无涯之C++ typename的起源与用法
- maven操作手顺
- TCP欺骗
- java笔记--day09--对多态的理解
- HttpURL网络获取资源之:GET方法
- SCU2016-01 G题(最大流 + floyd_warshall)
- Android开发中的tools命名空间的使用
- Linux学习第二天-文件系统和简单文件操作命令
- QT QDockWidget锚接部件 和 QTreeWidget 树形部件 构成树形选择项
- DNS欺骗
- HttpURLConnection:网络下载数据的工具类
- Android04--Android之下拉列表Spinner
- HttpURLConnection:访问服务器端,做登录-->get请求。参数是通过url来进行传递
- StarUML使用说明-指导手册