Flow Construction
Question:
N nodes and m water pipes are provided, which must meet the upper and lower boundaries. The minimum traffic at the starting point is met.
Algorithm:
This is the smallest stream ???? I don't know. You only need to know how to solve the maximum stream in the upper and lower bounds.
I learned a lot from this question. I know that the flow at the same point is the actual traffic value. Although I have seen it in books or papers before, I am not very impressed, but I understand it after this question. It is a little troublesome to output this question... We need to record the path each time, and then use the one we just mentioned. The flow at the same point is the actual traffic Value !!!!
#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <cstdio>#include <cstring>using namespace std;const int INF = 1 << 28;const int MAXN = 200 + 10;/////////////////////////////////////////上下界最小流struct Edge{ int from,to,cap,flow,cost; Edge(){}; 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 cur[MAXN],d[MAXN];bool vst[MAXN];int N,M,src,sink;//////////////////////////////////上下界网络流int sum;int in[MAXN],id[MAXN*MAXN],low[MAXN*MAXN];void init(){ src = N + 2; sink = src + 1; for(int i = 0;i <= sink;++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)); int sz = edges.size(); G[from].push_back(sz - 2); G[to].push_back(sz - 1);}bool BFS(){ memset(vst,0,sizeof(vst)); queue<int> Q; vst[src] = 1; d[src] = 0; Q.push(src); while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int i = 0;i < (int)G[x].size();++i){ Edge& e = edges[G[x][i]]; if(!vst[e.to] && e.cap > e.flow){ vst[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vst[sink];}int DFS(int x,int a){ if(x == sink||a == 0) return a; int flow = 0,f; for(int& i = cur[x];i < (int)G[x].size();++i){ Edge& e = edges[G[x][i]]; if(d[e.to] == d[x] + 1&&(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 flow = 0; while(BFS()){ memset(cur,0,sizeof(cur)); flow += DFS(src,INF); } return flow;}void solve(){ for(int i = 1;i <= N;++i){ if(in[i] > 0){ sum += in[i]; addEdge(src,i,in[i]); } else { addEdge(i,sink,-in[i]); } } sum -= maxFlow(); addEdge(N,1,INF); //是图变成无源无汇 int flow = maxFlow(); if(flow != sum){ puts("Impossible"); return; } int sz = edges.size(); //N --> 1 的容量 printf("%d\n",edges[sz - 2].flow); //反向弧的流量,即为正向真实流的流量!!! for(int i = 0;i < M;++i){ if(low[i] > 0) printf("%d%c",low[i],i == M - 1 ? '\n':' '); else printf("%d%c",edges[id[i]].flow,i == M - 1 ? '\n':' '); }}int main(){ while(scanf("%d%d",&N,&M) == 2){ init(); int x,y,c,d; sum = 0; memset(in,0,sizeof(in)); for(int i = 0; i < M;++i){ scanf("%d%d%d%d",&x,&y,&c,&d); if(d == 0){ //流量没限制 id[i] = edges.size(); addEdge(x,y,c); } else { //sum += c; in[x] -= c; in[y] += c; low[i] = c; // addEdge(src,y,c); //id[i] = edges.size(); //反向弧的流量,即为正向真实流的流量!!! //addEdge(x,sink,c); } } solve(); } return 0;}
Sgu flow construction