标签:scan poi determine win mit following font cto 序号
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
50
题目大意:
就是因为下大雨的时候约翰的农场就会被雨水给淹没。无奈下约翰不得不修建水沟,并且是网络水沟,并且聪明的约翰还控制了水的流速,本题就是让你求出最大流速,无疑要运用到求最大流了。
题中m为水沟数。n为水沟的顶点,接下来Si,Ei,Ci各自是水沟的起点,终点以及其容量。求源点1到终点n的最大流速。
注意重边
</pre></p><pre name="code" class="cpp"> EdmondsKarp算法写的: 邻接矩阵: </pre><pre name="code" class="cpp"> #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<queue> #define INF 0x3f3f3f3f using namespace std; const int M = 1000 + 50; int n, m; int r[M][M]; int pre[M];// 记录结点i的前向结点为pre[i] bool vist[M];// 记录结点i是否已訪问 bool BFS(int s, int t) //推断是否存在增广路 { queue<int>que; memset(pre, 0, sizeof(pre)); memset(vist, false, sizeof(vist)); pre[s] = s; vist[s] = true; que.push(s); int p; while( !que.empty() ) { p = que.front(); que.pop(); for(int i=1; i<=n; i++) { if(r[p][i]>0 && !vist[i]) { pre[i]=p; vist[i]=true; if( i==t ) return true; que.push(i); } } } return false; } int EK(int s, int t) { int maxflow = 0; while( BFS(s, t) ) { int d = INF; // 若有增广路径,则找出最小的delta for(int i=t; i!=s; i=pre[i]) d = min(d, r[ pre[i] ][i]); // 这里是反向边 for(int i=t; i!=s; i=pre[i]) { r[ pre[i] ][i] -= d;//方向边 r[i][ pre[i] ] += d;//方向边 } maxflow += d; } return maxflow; } int main() { while(cin>>m>>n) { memset(r, 0, sizeof(r)); for(int i=0; i<m; i++) { int from, to, rap; scanf("%d%d%d", &from, &to, &rap); r[from][to] += rap; } cout<<EK(1, n)<<endl; } return 0; }
邻接表(紫书上的模板):
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<queue> using namespace std; #define INF 0x3f3f3f3f; const int MAXN = 1000 + 50; struct Edge { int from, to, cap, flow; Edge (int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {} }; struct EdmondsKarp { int n, m; vector<Edge> edges; vector<int> G[MAXN]; int a[MAXN]; int p[MAXN]; void init(int n) { for(int i=0; i<n; i++) G[i].clear(); edges.clear(); } 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); } int Maxflow(int s, int t) { int flow = 0; for( ; ; ) { memset(a, 0, sizeof(a)); queue<int> Q; Q.push(s); a[s]=INF; 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( !a[e.to] && e.cap > e.flow ) { p[e.to] = G[x][i]; a[e.to] = min(a[x], e.cap-e.flow); Q.push(e.to); } } if( a[t] ) break; } if( ! a[t] ) break; for(int u=t; u!=s; u=edges[ p[u] ].from ) { edges[ p[u] ].flow += a[t]; edges[ p[u]^1 ].flow -= a[t]; } flow += a[t]; } return flow; } }; int main() { EdmondsKarp T; int n, m; while(scanf("%d%d", &m, &n) !=EOF) { T.init(n+1); for(int i=0; i<m; i++) { int a1, a2, a3; scanf("%d%d%d", &a1, &a2, &a3); T.AddEdge(a1, a2, a3); } printf("%d\n", T.Maxflow(1, n)); } return 0; }
Dinic算法:
#include <cstdio> #include <cstring> #include <queue> #define MAXN 205 #define INF 1000000000 using namespace std; struct Edge { int from, to, cap, flow; }; struct Dinic { int n, m, s, t; vector<Edge> edges; //边表.edges[e]和edges[e^1]互为反向弧 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 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() {//使用BFS计算出每个点在残量网络中到t的最短距离d. 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) {//使用DFS从S出发,沿着d值严格递减的顺序进行多路增广。 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; } }; Dinic g; int main() { int n, m, i, a, b, c; while (~scanf("%d%d", &m, &n)) { g.ClearAll(n + 1); for (i = 0; i < m; i++) { scanf("%d%d%d", &a, &b, &c); g.AddEdge(a, b, c); } int flow = g.Maxflow(1, n); printf("%d\n", flow); } return 0; }
HDU 1532||POJ1273:Drainage Ditches(最大流)
标签:scan poi determine win mit following font cto 序号
原文地址:http://www.cnblogs.com/gccbuaa/p/6923548.html