P3376 网络最大流模板(Dinic + dfs多路增广优化 + 炸点优化 + 当前弧优化)

匿名 (未验证) 提交于 2019-12-03 00:05:01

这里讲一下两种优化的实现以及正确性。

1、dfs多路增广优化

int dfs(int u,int res) {     if(u==T) return res;     for(int i=head[u];i!=-1;i=edge[i].next){         int v=edge[i].to;         if(flag[v]==flag[u]+1&&edge[i].val){             if(int k=dfs(v,min(res,edge[i].val))){                 edge[i].val-=k;                 edge[i^1].val+=k;                 return k;             }         }     }     return 0; }

int dfs(int u,int flow) {     int nowflow=0;     if(u==T) return flow;     for(int i=head[u];i!=-1;i=edge[i].next){         cur[u]=i;         int v=edge[i].to;         if(d[v]==d[u]+1&&edge[i].val>0){             if(int k=dfs(v,min(flow-nowflow,edge[i].val))){                 edge[i].val-=k;                 edge[i^1].val+=k;                 nowflow+=k;                 if(nowflow==flow) break;             }         }     }     return nowflow;//这里需要返回该点的总流量 }

2、炸点优化

int dfs(int u,int flow) {     int nowflow=0;     if(u==T) return flow;     for(int i=head[u];i!=-1;i=edge[i].next){         cur[u]=i;         int v=edge[i].to;         if(d[v]==d[u]+1&&edge[i].val>0){             if(int k=dfs(v,min(flow-nowflow,edge[i].val))){                 edge[i].val-=k;                 edge[i^1].val+=k;                 nowflow+=k;                 if(nowflow==flow) break;             }         }     }     if(!nowflow) d[u]=-1; // 炸点     return nowflow; }

3、当前弧优化

int dfs(int u,int flow) {     int nowflow=0;     if(u==T) return flow;     for(int i=cur[u];i!=-1;i=edge[i].next){         cur[u]=i; // 当前弧优化         int v=edge[i].to;         if(d[v]==d[u]+1&&edge[i].val>0){             if(int k=dfs(v,min(flow-nowflow,edge[i].val))){                 edge[i].val-=k;                 edge[i^1].val+=k;                 nowflow+=k;                 if(nowflow==flow) break;             }         }     }     if(!nowflow) d[u]=-1;     return nowflow; }

这三种优化会使得Dinic时间复杂度降低很多,这边测试是直接降了接近 300 MS 。

总代码如下:

#define IO freopen("test.in","r",stdin),freopen("test.out","w",stdout) #define inf 0x3f3f3f3f #define lson root<<1 #define rson root<<1|1 #include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <cassert> #include <iostream> #include <algorithm> #include <unordered_map> using namespace std; #define maxn 10008 #define inf 0x3f3f3f3f int N,M,S,T,cnt; int head[maxn],cur[maxn],d[maxn]; inline int read() {     int x=0,w=0;char ch=0;     while(!isdigit(ch)){w|=ch=='-';ch=getchar();}     while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}     return w?-x:x; } struct Edge {     int to;     int val;     int next; }edge[200008]; inline void add(int u,int v,int w) {     edge[++cnt].to=v;     edge[cnt].val=w;     edge[cnt].next=head[u];     head[u]=cnt;     return; } bool bfs() {     queue<int> q;     while(!q.empty()) q.pop();     for(int i=1;i<=N;i++) d[i]=-1;     d[S]=0;     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(d[v]==-1&&edge[i].val>0){                 d[v]=d[u]+1;                 q.push(v);             }         }     }     return d[T]!=-1; } int dfs(int u,int flow) {     int nowflow=0;     if(u==T) return flow;     for(int i=cur[u];i!=-1;i=edge[i].next){         cur[u]=i;         int v=edge[i].to;         if(d[v]==d[u]+1&&edge[i].val>0){             if(int k=dfs(v,min(flow-nowflow,edge[i].val))){                 edge[i].val-=k;                 edge[i^1].val+=k;                 nowflow+=k;                 if(nowflow==flow) break;             }         }     }     if(!nowflow) d[u]=-1;     return nowflow; } 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() {     //IO;     N=read(),M=read(),S=read(),T=read();     int A,B,C;     cnt=-1;     for(int i=1;i<=N;i++) head[i]=-1;     while(M--)     {         A=read(),B=read(),C=read();         add(A,B,C),add(B,A,0);     }     printf("%d\n",Dinic()); }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!