网络流板子
Posted vikyanite
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流板子相关的知识,希望对你有一定的参考价值。
Dinic模板
#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; //const int maxm = 1e3 * 2 + 10; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; struct Edge{ int to; int next; int w; }edge[maxn*2]; int head[maxn]; int cur[maxn];//当前弧优化数组 int n, m, s, t;//点数,边数,源点,汇点 int dis[maxn];//Bfs深度 int cnt = 0;//边数 int x; inline void init(){ cnt = 0; memset(head, -1, sizeof head); } inline void Add_Edge(int u, int v, int w){ edge[cnt].next = head[u]; edge[cnt].to = v; edge[cnt].w = w; head[u] = cnt++; } inline bool Bfs(){ for(int i = 1; i <= n; ++i) dis[i] = -1; dis[s] = 0; queue<int> q; q.push(s); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if(dis[v] == -1 && edge[i].w){//没有标记深度并且有残量 dis[v] = dis[u] + 1; q.push(v); } } } return dis[t] != -1; } inline int dfs(int u, int flow){ if(u == t) return flow; int del = flow; for(int i = cur[u]; i != -1; i = edge[i].next){ cur[u] = edge[i].next;//当前弧优化,下次直接从cur[u]开始增广,节省时间 int v = edge[i].to; if(dis[v] == dis[u] + 1 && edge[i].w > 0){//深度+1且残量大于0 int ans = dfs(v, min(del, edge[i].w));//木桶原理 edge[i].w -= ans;//正向弧减增广流量 edge[i ^ 1].w += ans;//反向弧加增广流量 del -= ans;//总流量减增广流量 if(del == 0) break;//总流量为0则不继续增广 } } return flow - del;//返回本次增广的流量 } inline int Dinic(){ int ans = 0; while(Bfs()){ for(int i = 1; i <= n; ++i) cur[i] = head[i]; ans += dfs(s, inf); } return ans; } int main(){ scanf("%d %d %d", &n, &m, &x); s = 1, t = n; init(); for(int i = 1; i <= m; ++i){ int u, v, w; scanf("%d %d %d", &u, &v, &w); Add_Edge(u, v, w); Add_Edge(v, u, 0); } int ans = Dinic(); if (!ans) cout << "Orz Ni Jinan Saint Cow!" << endl; else { int ans1 = ceil(x*1./ans); printf("%d %d ", ans, ans1); } return 0; }
ISAP模板
#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; //const int maxm = 1e3 * 2 + 10; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; int m,n,s,t, x, head[maxn], num_edge; int cur[maxn],deep[maxn],last[maxn],num[maxn]; //cur当前弧优化; last该点的上一条边; num桶 用来GAP优化 struct Edge{ int next,to,dis; }edge[maxn*2]; void add_edge(int from,int to,int dis) { edge[num_edge].to=to; edge[num_edge].dis=dis; edge[num_edge].next=head[from]; head[from]=num_edge++; } //bfs仅用于更新deep void bfs(int t) { queue<int>q; for (int i=0; i<=n; i++) cur[i]=head[i]; for (int i=1; i<=n; i++) deep[i]=n; deep[t]=0; q.push(t); while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i != -1; i=edge[i].next) { if (deep[edge[i].to]==n && edge[i^1].dis)//i^1是为了找反边 { deep[edge[i].to] = deep[now]+1; q.push(edge[i].to); } } } } int add_flow(int s,int t) { int ans=inf,now=t; while (now!=s) { ans=min(ans,edge[last[now]].dis); now=edge[last[now]^1].to; } now=t; while (now!=s) { edge[last[now]].dis-=ans; edge[last[now]^1].dis+=ans; now=edge[last[now]^1].to; } return ans; } int isap(int s,int t) { int now=s; int maxflow = 0; bfs(t);//搜出一条增广路 for (int i=1; i<=n; i++) num[deep[i]]++; while (deep[s]<n) { if (now==t) {//如果到达汇点就直接增广,重新回到源点进行下一轮增广 maxflow+=add_flow(s,t); now=s;//回到源点 } bool has_find=0; for (int i=cur[now]; i!=-1; i=edge[i].next) { if (deep[now]==deep[edge[i].to]+1 && edge[i].dis)//找到一条增广路 { has_find=true; cur[now]=i;//当前弧优化 now=edge[i].to; last[edge[i].to]=i; break; } } if (!has_find)//没有找到出边,重新编号 { int minn=n-1; for (int i=head[now]; i!=-1; i=edge[i].next)//回头找路径 if (edge[i].dis) minn=min(minn,deep[edge[i].to]); if ((--num[deep[now]])==0) break;//GAP优化 出现了断层 num[deep[now]=minn+1]++; cur[now]=head[now]; if (now!=s) now=edge[last[now]^1].to; } } return maxflow; } int main(){ num_edge = 0; memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&x); for(int i=0;i<m;i++){ int u,v,cap; scanf("%d%d%d",&u,&v,&cap); add_edge(u,v,cap); add_edge(v,u,0); } s = 1, t = n; int ans = isap(s,t); if (!ans) cout << "Orz Ni Jinan Saint Cow!" << endl; else { int ans2 = ceil(x*1./ans); printf("%d %d ", ans, ans2); } return 0; }
以上是关于网络流板子的主要内容,如果未能解决你的问题,请参考以下文章