链接:https://vjudge.net/problem/HDU-3549
题意:
给定多张图,求从1到n的最大流
思路:
网络流最大流
增广路算法,具体看注释。
代码:
#include <iostream> #include <memory.h> #include <vector> #include <map> #include <algorithm> #include <cstdio> #include <math.h> #include <queue> #include <string> using namespace std; typedef long long LL; const int MAXM = 1000 + 10; const int MAXN = 20; const int INF = 1e9 + 10; int n, m; struct Edge { int _from, _to, _cap, _flow; Edge(int from, int to, int cap, int flow):_from(from), _to(to), _cap(cap), _flow(flow){}; }; vector<Edge> edges;//记录每条边 vector<int> G[MAXN];//记录图,每个节点的边 int a[MAXN], p[MAXN]; //a数组记录每次找增广路时候每个节点对应能加的流 //p数组记录流经的点对应的线路的编号 void Init() { edges.clear(); for (int i = 0;i < n;i++) G[i].clear(); } int Solve() { int flow = 0;//总流量 while (1) { memset(a, 0, sizeof(a));//每次找增广路初始化 queue<int> que;//每次bfs的队列 que.push(1); a[1] = INF; while (!que.empty()) { int x = que.front(); que.pop(); for (int i = 0;i < G[x].size();i++) { Edge & e = edges[G[x][i]]; if (!a[e._to] && e._cap > e._flow) { //a为0表示没有流过这个点同时流量小于容量 p[e._to] = G[x][i]; a[e._to] = min(a[x], e._cap - e._flow); //能流的流量是线路最大流量和上一个节点的值中的较小值 que.push(e._to);//新节点进队 } } if (a[n] > 0)//如果流到了终点,break break; } if (a[n] == 0)//如果终点流不到,表示增广路找不到, break; for (int u = n;u != 1;u = edges[p[u]]._from) { edges[p[u]]._flow += a[n]; edges[p[u] ^ 1]._flow -= a[n];//表示与正向对应的反向的边 } flow += a[n]; } return flow; } int main() { int t; int l, r, c, cnt = 0; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); Init(); for (int i = 1;i <= m;i++) { scanf("%d%d%d", &l, &r, &c); edges.push_back(Edge(l, r, c, 0)); edges.push_back(Edge(r, l, 0, 0));//增加反向边 保证能找到最大流 G[l].push_back(edges.size() - 2); G[r].push_back(edges.size() - 1); } cout << "Case " << ++cnt << ": "; cout << Solve() << endl; } return 0; }