这里讲一下两种优化的实现以及正确性。
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()); } 来源:博客园
作者:大头冲锋车丶
链接:https://www.cnblogs.com/Absofuckinglutely/p/11520363.html