最大流模板
处理重边的+(优化)
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; struct Edge { int from,to,cap,flow; Edge(){} Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(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]; //d[i]表从起点s到i点的距离(层次) int cur[maxn]; //cur[i]表当前正访问i节点的第cur[i]条弧 void init(int n,int s,int t) { this->n=n,this->s=s,this->t=t; 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() { memset(vis,0,sizeof(vis)); queue<int> Q;//用来保存节点编号的 Q.push(s); d[s]=0; vis[s]=true; 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]=true; d[e.to] = d[x]+1; Q.push(e.to); } } } return vis[t]; } //a表示从s到x目前为止所有弧的最小残量 //flow表示从x到t的最小残量 int DFS(int x,int a) { if(x==t || a==0)return a; int flow=0,f;//flow用来记录从x到t的最小残量 for(int& i=cur[x]; i<G[x].size(); i++)///注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的 { 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; } } if(!flow) d[x] = -1;///炸点优化 return flow; } int Maxflow() { int flow=0; while(BFS()) { memset(cur,0,sizeof(cur)); flow += DFS(s,INF); } return flow; } }DC; int main(void ) { int N,M,S,T; while(scanf("%d%d%d%d",&N,&M,&S,&T)!=EOF) { DC.init(N,S,T); while(M--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); DC.AddEdge(u,v,w); } printf("%d",DC.Maxflow()); } }
比上面快一点
#include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cstdio> #include<vector> #include<cmath> #include<queue> #define ll long long #define maxn 23500 #define maxe 1000000 #define inf 1100000000 using namespace std; struct Edge { int u, v, cap; int nxt; }edge[maxe]; int head[maxn]; int n, m; struct Dicnic { int level[maxn]; int iter[maxn]; int add; void init(){ add = 0; memset(head, -1, sizeof(head)); memset(iter, -1, sizeof(iter)); } void insert(int u, int v, int c){ edge[add].u = u; edge[add].v = v; edge[add].cap = c; edge[add].nxt = head[u]; head[u] = add++; edge[add].u = v; edge[add].v = u; edge[add].cap = 0; edge[add].nxt = head[v]; head[v] = add++; } void bfs(int s){ memset(level, -1, sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while (!que.empty()){ int v = que.front(); que.pop(); for (int i = head[v]; i != -1; i = edge[i].nxt){ Edge &e = edge[i]; if (e.cap > 0 && level[e.v] < 0){ level[e.v] = level[v] + 1; que.push(e.v); } } } } int dfs(int v, int t, int f){ if (v == t) return f; for (int &i = iter[v]; i != -1; i = edge[i].nxt){ Edge &e = edge[i]; Edge &reve = edge[i ^ 1]; if (e.cap > 0 && level[v] < level[e.v]){ int d = dfs(e.v, t, min(f, e.cap)); if (d>0){ e.cap -= d; reve.cap += d; return d; } } } return 0; } int max_flow(int s, int t){ int flow = 0; for (;;){ bfs(s); if (level[t] < 0) return flow; memcpy(iter, head, sizeof(iter)); int f; while ((f = dfs(s, t, inf))>0){ flow += f; } } } }net; int a[maxn], b[maxn]; int main() { while (cin >> n >> m){ net.init(); int s = 0, t = n + 1; for (int i = 1; i <= n; i++) { scanf("%d", a + i); scanf("%d", b + i); net.insert(i, t, a[i]); net.insert(s, i, b[i]); } int ui, vi, wi; for (int i = 0; i < m; i++){ scanf("%d%d%d", &ui, &vi, &wi); net.insert(ui, vi, wi); net.insert(vi, ui, wi); } printf("%d ", net.max_flow(s,t)); } return 0; }
还行
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; const int maxn = 1000001; const int INF = 0x3f3f3f; struct no { int to; int cap; int rev; }; vector<no> G[maxn]; int level[maxn];///顶点到源点的距离标记 int iter[maxn];///当前弧,在其之前的边没有用了 void add(int from,int to,int cap) { G[from].push_back((no){to,cap,G[to].size()}); G[to].push_back((no){from,0,G[from].size()-1}); } void bfs(int s) { memset(level,-1,sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while(!que.empty()) { int v = que.front( ) ; que.pop( ); for(int i=0 ; i<G[v].size( ) ; i++) { no &e = G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to] = level[v]+1; que.push(e.to); } } } } int dfs(int v,int t, int f) { if(v==t) return f; for(int &i=iter[v];i<G[v].size();++i)//这里是引用,i++的同时iter也++,其实相当于上个的used,不过不用判断了 { no &e = G[v][i]; if(e.cap>0 && level[e.to]>level[v]) { int d=dfs(e.to,t,min(e.cap,f)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t) { int flow = 0; for( ; ; ) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,INF))>0) flow+=f; } } int main() { int s,t,m,n; scanf("%d%d%d%d",&n,&m,&s,&t); int u,v,cap; for(int i=0;i<m;++i) { scanf("%d%d%d",&u,&v,&cap); add(u,v,cap); } printf("%d",max_flow(s,t)); return 0; }
神奇代码:巨快
#include <bits/stdc++.h> const int MAXN = 1e6 + 10; const int INF = 0x3f3f3f3f; struct Node { int v, f, index; Node(int v, int f, int index) : v(v), f(f), index(index) {} }; int n, m, s, t; std::vector<Node> edge[MAXN]; std::vector<int> list[MAXN], height, count, que, excess; typedef std::list<int> List; std::vector<List::iterator> iter; List dlist[MAXN]; int highest, highestActive; typedef std::vector<Node>::iterator Iterator; void init() { for(int i=0; i<=n; i++) edge[i].clear(); } void addEdge(const int u, const int v, const int f) { edge[u].push_back(Node(v, f, edge[v].size())); edge[v].push_back(Node(u, 0, edge[u].size() - 1)); } void globalRelabel(int n, int t) { height.assign(n, n); height[t] = 0; count.assign(n, 0); que.clear(); que.resize(n + 1); int qh = 0, qt = 0; for (que[qt++] = t; qh < qt;) { int u = que[qh++], h = height[u] + 1; for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) { if (height[p->v] == n && edge[p->v][p->index].f > 0) { count[height[p->v] = h]++; que[qt++] = p->v; } } } for (int i = 0; i <= n; i++) { list[i].clear(); dlist[i].clear(); } for (int u = 0; u < n; ++u) { if (height[u] < n) { iter[u] = dlist[height[u]].insert(dlist[height[u]].begin(), u); if (excess[u] > 0) list[height[u]].push_back(u); } } highest = (highestActive = height[que[qt - 1]]); } void push(int u, Node &e) { int v = e.v; int df = std::min(excess[u], e.f); e.f -= df; edge[v][e.index].f += df; excess[u] -= df; excess[v] += df; if (0 < excess[v] && excess[v] <= df) list[height[v]].push_back(v); } void discharge(int n, int u) { int nh = n; for (Iterator p = edge[u].begin(); p != edge[u].end(); ++p) { if (p->f > 0) { if (height[u] == height[p->v] + 1) { push(u, *p); if (excess[u] == 0) return; } else { nh = std::min(nh, height[p->v] + 1); } } } int h = height[u]; if (count[h] == 1) { for (int i = h; i <= highest; i++) { for (List::iterator it = dlist[i].begin(); it != dlist[i].end(); ++it) { count[height[*it]]--; height[*it] = n; } dlist[i].clear(); } highest = h - 1; } else { count[h]--; iter[u] = dlist[h].erase(iter[u]); height[u] = nh; if (nh == n) return; count[nh]++; iter[u] = dlist[nh].insert(dlist[nh].begin(), u); highest = std::max(highest, highestActive = nh); list[nh].push_back(u); } } int hlpp(int n, int s, int t) { if (s == t) return 0; highestActive = 0; highest = 0; height.assign(n, 0); height[s] = n; iter.resize(n); for (int i = 0; i < n; i++) if (i != s) iter[i] = dlist[height[i]].insert(dlist[height[i]].begin(), i); count.assign(n, 0); count[0] = n - 1; excess.assign(n, 0); excess[s] = INF; excess[t] = -INF; for (int i = 0; i < (int)edge[s].size(); i++) push(s, edge[s][i]); globalRelabel(n, t); for (int u /*, res = n*/; highestActive >= 0;) { if (list[highestActive].empty()) { highestActive--; continue; } u = list[highestActive].back(); list[highestActive].pop_back(); discharge(n, u); // if (--res == 0) globalRelabel(res = n, t); } return excess[t] + INF; } int main() { while(~scanf("%d %d %d %d", &n, &m, &s, &t)){ init(); for (int i = 0, u, v, f; i < m; i++) { scanf("%d %d %d", &u, &v, &f); addEdge(u, v, f); } printf("%d", hlpp(n + 1, s, t));///点是1~n范围的话,貌似要 n+1 } return 0; }
最大流的最小费用流模板
struct Edge { int from,to,cap,flow,cost; Edge(){} Edge(int f,int t,int c,int fl,int co):from(f),to(t),cap(c),flow(fl),cost(co){} }; struct MCMF { int n,m,s,t; vector<Edge> edges; vector<int> G[maxn]; bool inq[maxn]; //是否在队列 int d[maxn]; //Bellman_ford单源最短路径 int p[maxn]; //p[i]表从s到i的最小费用路径上的最后一条弧编号 int a[maxn]; //a[i]表示从s到i的最小残量 //初始化 void init(int n,int s,int t) { this->n=n, this->s=s, this->t=t; edges.clear(); for(int i=0;i<n;++i) G[i].clear(); } //添加一条有向边 void AddEdge(int from,int to,int cap,int cost) { edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } //求一次增广路 bool BellmanFord(int &flow, int &cost) { for(int i=0;i<n;++i) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0, a[s]=INF, inq[s]=true, p[s]=0; queue<int> Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]=false; for(int i=0;i<G[u].size();++i) { Edge &e=edges[G[u][i]]; if(e.cap>e.flow && d[e.to]>d[u]+e.cost) { d[e.to]= d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]= min(a[u],e.cap-e.flow); if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; } } } } if(d[t]==INF) return false; flow +=a[t]; cost +=a[t]*d[t]; int u=t; while(u!=s) { edges[p[u]].flow += a[t]; edges[p[u]^1].flow -=a[t]; u = edges[p[u]].from; } return true; } //求出最小费用最大流 int Min_cost() { int flow=0,cost=0; while(BellmanFord(flow,cost)); return cost; } }MM;
struct Edge { int from,to,cap,flow,cost; Edge(int u,int v,int ca,int f,int co):from(u),to(v),cap(ca),flow(f),cost(co){}; }; struct MCMF { int n,m,s,t; vector<Edge> edges; vector<int> G[maxn]; int inq[maxn];//是否在队列中 int d[maxn];//距离 int p[maxn];//上一条弧 int a[maxn];//可改进量 void init(int n)//初始化 { this->n=n; for(int i=0;i<=n;i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,int cost)//加边 { edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); int m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool SPFA(int s,int t,int &flow,int &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost { for(int i=0;i<n;i++) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0;inq[s]=1;p[s]=0;a[s]=INF; queue<int> Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]--; for(int i=0;i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(e.cap>e.flow && d[e.to]>d[u]+e.cost)//满足可增广且可变短 { d[e.to]=d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]=min(a[u],e.cap-e.flow); if(!inq[e.to]) { inq[e.to]++; Q.push(e.to); } } } } if(d[t]==INF) return false;//汇点不可达则退出 flow+=a[t]; cost+=d[t]*a[t]; int u=t; while(u!=s)//更新正向边和反向边 { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } int MincotMaxflow(int s,int t) { int flow=0,cost=0; while(SPFA(s,t,flow,cost)); return cost; } }MM;
固定流量的最小费用
#include <iostream> #include <queue> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int maxn = 3000; const int INF = 0x3f3f3f3f; typedef pair<int,int> P; struct Edge { int to, cap, cost, rev; Edge(int to_, int cap_, int cost_, int rev_):to(to_),cap(cap_),cost(cost_),rev(rev_){} }; vector<Edge> G[maxn]; int V, n, m, relation[55][55]; int h[maxn], dist[maxn], prevv[maxn], preve[maxn]; void add_edge(int from, int to, int cap, int cost) { G[from].push_back(Edge(to, cap, cost, G[to].size())); G[to].push_back(Edge(from, 0, -cost, G[from].size()-1)); } int min_cost_flow(int s, int t, int f) { int res = 0; memset(h, 0, sizeof(h)); while(f > 0) { priority_queue<P, vector<P>, greater<P> > pq; fill(dist, dist + V, INF); dist[s] = 0; pq.push(P(0, s)); while(!pq.empty()) { P p = pq.top(); pq.pop(); int v = p.second; if(dist[v] < p.first) continue; for(int i = 0; i < G[v].size(); i++) { Edge& e = G[v][i]; if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) { dist[e.to] = dist[v] + e.cost + h[v] - h[e.to]; prevv[e.to] = v; preve[e.to] = i; pq.push(P(dist[e.to], e.to)); } } } if(dist[t] == INF) return -1; for(int v = 0; v < V; v++) h[v] += dist[v]; int d = f; for(int v = t; v != s; v = prevv[v]) { d = min(d, G[prevv[v]][preve[v]].cap); } f -= d; res += d * h[t]; for(int v = t; v != s; v = prevv[v]) { Edge& e = G[prevv[v]][preve[v]]; e.cap -= d; G[v][e.rev].cap += d; } } return res; }
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<cctype> #include<string> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; #define end() return 0 typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxn = 4000 + 5; const int INF = 0x7f7f7f7f; struct Edge{ int from,to,cap,flow,cost; Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){} }; struct MCMF{ int n,m; vector<Edge>edge; //边数的两倍 vector<int>G[maxn]; //邻接表,G[i][j]表示i的第j条边在e数组中的序号 int inq[maxn]; //是否在队列 int d[maxn]; //Bellman-Ford int p[maxn]; //上一条弧 int a[maxn]; //可改进量 void init(int n){ this -> n = n; for(int i=0;i<=n;i++) G[i].clear(); edge.clear(); } void addEdge(int from,int to,int cap,int cost){ edge.push_back(Edge(from,to,cap,0,cost)); edge.push_back(Edge(to,from,0,0,-cost)); m=edge.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int s,int t,int& flow,int& cost){ memset(d,INF,sizeof(d)); memset(inq,0,sizeof(inq)); d[s]=0; inq[s]=1; p[s]=0; a[s]=INF; queue<int>q; q.push(s); while(!q.empty()){ int u=q.front();q.pop(); inq[u]=0; for(int i=0;i<G[u].size();i++){ Edge& e=edge[G[u][i]]; if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){ d[e.to]=d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]=min(a[u],e.cap-e.flow); if(!inq[e.to]){ q.push(e.to); inq[e.to]=1; } } } } if(d[t]==INF) return false; flow+=a[t]; cost+=d[t]; if(flow==2) return false; for(int u=t;u!=s;u=edge[p[u]].from){ edge[p[u]].flow+=a[t]; edge[p[u]^1].flow-=a[t]; } return true; } //需要保证初始网络中没有负权圈 int MincostMaxflow(int s,int t){ int flow=0,cost=0; while(BellmanFord(s,t,flow,cost)); return cost; } }; int N,M; int a,b,c; MCMF mcmf; void input(){ scanf("%d%d",&N,&M); mcmf.init(N); for(int i=0;i<M;i++){ scanf("%d%d%d",&a,&b,&c); mcmf.addEdge(a,b,1,c); mcmf.addEdge(b,a,1,c); } } void solve(){ printf("%d ",mcmf.MincostMaxflow(1,N)); } int main(){ input(); solve(); end(); }
区别是81行多了个 if(flow==2) return false : 意思是控制流量为2;