UVA11248【最大流最小割入门】
来源:互联网 发布:js控制显示隐藏 编辑:程序博客网 时间:2024/06/06 23:16
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2205
给定一个有向网络,每条边均有一个容量。问是否存在一个从点1->n,流量为C的流。如果不存在,是否可以恰好修改一条弧的容量,使得这样的流存在?
第一行输入 N ,E, C (n个点, e条边)
下面e行u v cap 表示边
求最大流,如果流量>=c,则输出possible
否则修改边,边一定是最小割中的边。
依次把边增加到C中,然后求最大流,看最大流是否达到C
优化:求完最大流之后保存,每次在此基础上增广
ISAP
#include <cstdio>#include <cstring>#include <queue>#include <vector>#include <algorithm>using namespace std;const int maxn=100+10;const int INF = 1000000000;struct Edge{int from, to, cap, flow; };bool operator < (const Edge& a, const Edge& b) { return a.from < b.from || (a.from == b.from && a.to < b.to);}struct ISAP{ int n, m, s, t; vector<Edge> edges; vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[maxn]; // BFS使用 int d[maxn]; // 从起点到i的距离 int cur[maxn]; // 当前弧指针 int p[maxn]; // 可增广路上的上一条弧 int num[maxn]; // 距离标号计数 void AddEdge(int from, int to, int cap) { edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(t); vis[t] = 1; d[t] = 0; while(!Q.empty()) { int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]^1]; if(!vis[e.from] && e.cap > e.flow) { vis[e.from] = 1; d[e.from] = d[x] + 1; Q.push(e.from); } } } return vis[s]; } void ClearAll(int n) { this->n = n; for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void ClearFlow() { for(int i = 0; i < edges.size(); i++) edges[i].flow = 0; } int Augment(){ int x=t,a=INF; while(x!=s){ Edge &e=edges[p[x]]; a=min(a,e.cap-e.flow); x=edges[p[x]].from; } x=t; while(x != s) { edges[p[x]].flow += a; edges[p[x]^1].flow -= a; x = edges[p[x]].from; } return a; } int Maxflow(int s, int t, int need) { this->s = s; this->t = t; int flow = 0; BFS(); memset(num, 0, sizeof(num)); for(int i = 0; i < n; i++) num[d[i]]++; int x = s; memset(cur, 0, sizeof(cur)); while(d[s] < n) { if(x == t) { flow += Augment(); if(flow >= need) return flow; x = s; } int ok = 0; for(int i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance ok = 1; p[e.to] = G[x][i]; cur[x] = i; // 注意 x = e.to; break; } } if(!ok) { // Retreat int m = n-1; // 初值注意 for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(e.cap > e.flow) m = min(m, d[e.to]); } if(--num[d[x]] == 0) break; num[d[x] = m+1]++; cur[x] = 0; // 注意 if(x != s) x = edges[p[x]].from; } } return flow; } vector<int> Mincut() { // call this after maxflow BFS(); vector<int> ans; for(int i = 0; i < edges.size(); i++) { Edge& e = edges[i]; if(!vis[e.from] && vis[e.to] && e.cap > 0) ans.push_back(i); } return ans; } void Reduce() { for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow; } void print() { printf("Graph:\n"); for(int i = 0; i < edges.size(); i++) printf("%d->%d, %d, %d\n", edges[i].from, edges[i].to , edges[i].cap, edges[i].flow); }};ISAP g;int main(){int n,e,c,kase=0;while(scanf("%d%d%d",&n,&e,&c)==3&&n){g.ClearAll(n);while(e--) {//读入边 int b1, b2, fp; scanf("%d%d%d", &b1, &b2, &fp); g.AddEdge(b1-1, b2-1, fp); }int flow = g.Maxflow(0, n-1, INF); printf("Case %d: ", ++kase); if(flow >= c) printf("possible\n"); else { vector<int> cut = g.Mincut(); g.Reduce(); vector<Edge> ans; for(int i = 0; i < cut.size(); i++) { Edge& e = g.edges[cut[i]]; e.cap = c; g.ClearFlow(); if(flow + g.Maxflow(0, n-1, c-flow) >= c) ans.push_back(e); e.cap = 0; } if(ans.empty()) printf("not possible\n"); else { sort(ans.begin(), ans.end()); printf("possible option:(%d,%d)", ans[0].from+1, ans[0].to+1); for(int i = 1; i < ans.size(); i++) printf(",(%d,%d)", ans[i].from+1, ans[i].to+1); printf("\n"); } } } return 0;}
Dinic
#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<algorithm>using namespace std;const int maxn = 100 + 10;const int INF = 1000000000;struct Edge { int from, to, cap, flow;};bool operator < (const Edge& a, const Edge& b) { return a.from < b.from || (a.from == b.from && a.to < b.to);}struct Dinic { int n, m, s, t; vector<Edge> edges; // 边数的两倍 vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[maxn]; // BFS使用 int d[maxn]; // 从起点到i的距离 int cur[maxn]; // 当前弧指针 void ClearAll(int n) { for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void ClearFlow() { for(int i = 0; i < edges.size(); i++) edges[i].flow = 0; } void AddEdge(int from, int to, int cap) { edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); vis[s] = 1; d[s] = 0; while(!Q.empty()) { int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int& i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while(BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } vector<int> Mincut() { // call this after maxflow vector<int> ans; for(int i = 0; i < edges.size(); i++) { Edge& e = edges[i]; if(vis[e.from] && !vis[e.to] && e.cap > 0) ans.push_back(i); } return ans; } void Reduce() { for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow; }};Dinic g;int main() { int n, e, c, kase = 0; while(scanf("%d%d%d", &n, &e, &c) == 3 && n) { g.ClearAll(n); while(e--) { int b1, b2, fp; scanf("%d%d%d", &b1, &b2, &fp); g.AddEdge(b1-1, b2-1, fp); } int flow = g.Maxflow(0, n-1); printf("Case %d: ", ++kase); if(flow >= c) printf("possible\n"); else { vector<int> cut = g.Mincut(); g.Reduce(); vector<Edge> ans; for(int i = 0; i < cut.size(); i++) { Edge& e = g.edges[cut[i]]; e.cap = c; g.ClearFlow(); if(flow + g.Maxflow(0, n-1) >= c) ans.push_back(e); e.cap = 0; } if(ans.empty()) printf("not possible\n"); else { sort(ans.begin(), ans.end()); printf("possible option:(%d,%d)", ans[0].from+1, ans[0].to+1); for(int i = 1; i < ans.size(); i++) printf(",(%d,%d)", ans[i].from+1, ans[i].to+1); printf("\n"); } } } return 0;}
0 0
- UVA11248【最大流最小割入门】
- UVa11248 Frequency Hopping(最大流+最小割)
- 最大流最小割算法入门理解
- 最大流最小割算法入门理解
- 最大流/最小割
- 最大流最小割
- 最大流最小割
- 最大流最小割
- 最大流最小割
- 网络流(最大流,最小割)基础入门详解
- 最大流最小割定理
- 最大流-最小割简介
- 最大流最小割定理
- poj3308 最大流最小割
- 最小割转最大流
- 最大流和最小割
- 最小割最大流记录
- hdu2435最大流最小割
- block为什么用copy?利用runtime运行时的objc_方法为分类扩充成员变量
- adb 命令操作
- Keil 生成HEX时数据大小限制问题解决办法
- 用flexdashboard包创建交互式仪表盘:比shiny更简单
- 10个帮程序员减压放松的网站
- UVA11248【最大流最小割入门】
- NPAPI插件开发详细记要:插件运行流程分析
- linux查询cpu
- Socket 数据通信
- Majority Element解决:Moore's Voting Algorithm
- 好消息! 不用再羡慕Python有jupyter 我R也有Notebook了
- Maven 之 No compiler is provided in this environment
- plus.webview预创建界面
- myeclipse配置gradle插件