UVA 11594 UVA11603(与hdu4700类似) 点对点的最小割 Gomory-Hu 和Gusfield算法学习
来源:互联网 发布:mac 获取当前用户名 编辑:程序博客网 时间:2024/06/05 14:08
UVA 11594:Gusfield算法
题意: 给你n个点的容量网络图(n <= 100), 求出两两之间的最大流(最小割)
算法概述: 原先所有点在一个集合, 每次任选一个集合进行处理, 在集合内任选2个点,求一次最小割s-t,然后用s-t割更新 被这个割所能切割的点对(点对为已经选过的所有点组合出的任意两点之间的点对),直到所有集合中点的个数为1时结束。
code在下面
UVA 11603: Gomory-Hu算法
题意:n个点(n <= 200), 给你任意两点间的最大流(最小割), 让你构造一个容量网络满足这个条件。
分析:我们只要构造一个解就可以了,解可以是一颗树, 因为当解成环时, 总可以去掉环上的一条边,然后把这条边的容量加到其它所有该环内的边上去(可以自己去验证一下)。那么问题就变为如何构造这样一棵树
算法概述:我们每次找出所有点对中没有选过的最小的最小割,然后加入树边,然后就可以递归成 分别构造用该树边连接的2个集合的一颗树(子问题), 2个集合是用当前选的s-t割给割开来的。直到子集合的点数小于等于1的情况就结束。
为什么选最小的最小割:因为这样保证之后选的s-t割比之前的大,这样就不会把前面s-t割割断。
如何判不可能:
1.当点数>= 2时不能分成2个集合
2.分别两个集合内找一点,存在这两点之间的最小割 大于 当前选的s-t割。
code在下面
UVA 11594:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 203;const int inf = 1e9;struct Edge {int v, c, next;Edge(){}Edge(int v, int c, int next) : v(v), c(c), next(next) {}}edge[maxn*maxn<<1];int n, m;int head[maxn], E;void init() {E = 0;memset(head, -1, sizeof(head));}void add(int s, int t, int c) {edge[E] = Edge(t, c, head[s]);head[s] = E++;edge[E] = Edge(s, 0, head[t]);head[t] = E++;}int gap[maxn], dis[maxn], pre[maxn], cur[maxn];int sap(int s, int t, int n) // s 源点,t汇点,n顶点总数 { int i; for(i = 0; i <= n; i++) { dis[i] = gap[i] = 0; cur[i] = head[i]; } gap[0] = n; int u = pre[s] = s, maxf = 0, aug = inf, v; while(dis[s] < n) { loop: for(i = cur[u]; ~i; i = edge[i].next) { v = edge[i].v; if(edge[i].c && dis[u] == dis[v] + 1) { aug = min(aug, edge[i].c); pre[v] = u; cur[u] = i; u = v; if(u == t) { while(u != s) { u = pre[u]; edge[cur[u]].c -= aug; edge[cur[u] ^ 1].c += aug; } maxf += aug; aug = inf; } goto loop; } } int d = n; for(i = head[u]; ~i; i = edge[i].next) { v = edge[i].v; if(edge[i].c && dis[v] < d) { d = dis[v]; cur[u] = i; } } if(!(--gap[dis[u]])) break; ++gap[dis[u] = d + 1]; u = pre[u]; } return maxf;}//************************int ans[maxn][maxn], p[maxn]; // p[i]: 点i的集合编号bool mk[maxn];void dfs(int u) {mk[u] = 1;int i;for(i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(!mk[v] && edge[i].c) dfs(v);}}void solve(int n) {int i, j;for(i = 0; i < n; i++) {for(j = 0; j < n; j++) {ans[i][j] = inf;}p[i] = 0;}for(i = 1; i < n; i++) {for(j = 0; j < E; j += 2) { //把图还原成原图edge[j].c += edge[j^1].c;edge[j^1].c = 0;}for(j = 0; j < n; j++) mk[j] = 0;int cut = sap(i, p[i], n);//算法中取集合里的任意两点:这里我们有规则地取。ans[i][p[i]] = ans[p[i]][i] = cut;dfs(i);//找出被s-t割割掉后的一个集合,那么剩下的点就是另外一个集合for(j = i+1; j < n; j++) if(mk[j] && p[i] == p[j]) //找出的集合更新集合编号p[j] = i;for(j = 0; j < i; j++)//用当前s-t割去更新被其割掉的 已经选过的所有点组成的点对ans[i][j] = ans[j][i] = min(cut, ans[p[i]][j]);}for(i = 0; i < n; i++) for(j = 0; j < n; j++) { if(i == j) printf("0"); else printf("%d", ans[i][j]); if(j == n-1) puts(""); else printf(" "); }}int tp;int main() {int i, j, cas;scanf("%d", &cas);for(int ca = 1; ca <= cas; ca++) { scanf("%d", &n);printf("Case #%d:\n", ca);if(!n) continue;init();for(i = 0; i < n; i++)for(j = 0; j < n; j++) {scanf("%d", &tp);if(tp) add(i, j, tp);}solve(n);}return 0;}
UVA 11603:
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int inf = 1e9+7;int n;int cap[204][204];struct node {int u, v, c;};vector <node> ans;bool dfs(vector <int> v) { int Min = inf, i, j, sz = v.size(); if(sz <= 1) return 1; for(i = 0; i < sz; i++) for(j = i+1; j < sz; j++) if(cap[v[i]][v[j]] < Min) Min = cap[v[i]][v[j]]; vector <int> l, r; l.push_back(v[0]); for(i = 1; i < sz; i++) if(cap[v[0]][v[i]] > Min) l.push_back(v[i]); else r.push_back(v[i]); if(l.empty() || r.empty()) return 0; for(i = 0; i < l.size(); i++) for(j = 0; j < r.size(); j++) if(cap[l[i]][r[j]] != Min) return 0; if(Min > 0)ans.push_back(node{l[0], r[0], Min}); return dfs(l) && dfs(r);}int main() { int i, j, cas, ca = 1; scanf("%d", &cas); while(cas--) { scanf("%d", &n); vector <int> v; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) scanf("%d", &cap[i][j]); } printf("Case #%d: ", ca++); ans.clear(); for(i = 0; i < n; i++) v.push_back(i); if(dfs(v)) { printf("%d\n", ans.size()); for(i = 0; i < ans.size(); i++) printf("%d %d %d\n", ans[i].u, ans[i].v, ans[i].c); } else puts("Impossible"); } return 0;}
- UVA 11594 UVA11603(与hdu4700类似) 点对点的最小割 Gomory-Hu 和Gusfield算法学习
- 【BZOJ2229】[Zjoi2011]最小割【Gomory-Hu树】
- 最小割树Gomory-Hu tree
- [BZOJ4519] 不同的最小割 - 分治,最小割(Gomory-Hu Tree)
- Gomory-Hu tree (最小割树) 介绍及实现
- BZOJ 4519([Cqoi2016]不同的最小割-Gusfield算法)
- UVA 11594(All Pairs Maximum Flow-两两之间的最大流,Gusfield算法)
- uva 11248 最小割
- UVA 1515 (最小割)
- sw算法求最小割学习
- sw算法求最小割学习(*)
- 最大流和最小割算法
- 最大流和最小割:Edmonds_Karp算法
- 无向图的最小割算法
- 最小割算法
- 最小割算法
- opencv学习_10 (图像和轮廓的匹配(hu矩))
- opencv学习_10 (图像和轮廓的匹配(hu矩))
- 递归求数组最大最小值(分治思想)
- 解决MSN无法登录问题的意外收获
- 2013软创基地年度大会(深圳站 20131102)——敏捷落地!
- c++设计模式--单例模式
- [转]C++中运算符优先级表
- UVA 11594 UVA11603(与hdu4700类似) 点对点的最小割 Gomory-Hu 和Gusfield算法学习
- poj 2001 Shortest Prefixes
- RISC和CICS指令流水线的区别
- Handler
- View 5应用之三:手动池管理物理机
- [Codecademy] HTML&CSS第九课 :CSS Selectors
- 1.1介绍与多项式曲线拟合(Polynomial Curve Fitting)
- 数学之路(3)-机器学习(3)-机器学习算法-SVM[8]
- BNU 32788 The best trade path (有向图的最小环)