最大流Dinic算法的一些优化 [网络流][最大流]
明天省夏要讲网络流啦!晚上翻出自己的模板发现是蓝书模板QwQ。。拿出以前的提交代码(AC过的?)
曾经的提交记录
在luogu上重新提交一遍,结果gg...OVO
没有去除多余的inline
去除了多余的inline
论强数据练考验模板的好处?
于是决定自造一份正常的模板。。。
主要的优化有三——
(1) 当前弧优化,防止因重复访问一条边造成效率降低。
(2) 记录无法增广的点。
(3) 玄学优化?在Dinic的bfs过程中找到一条可增广的路径就返回(由于bfs的低效?),此优化在luogu的数据中表现良好。
具体可以看注释
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<vector> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 8 int read(){ 9 bool flag=0; 10 char ch; 11 int re=0; 12 while((ch=getchar())!='-'&&(ch<'0'||ch>'9')); 13 ch=='-'?flag=1:re=ch-'0'; 14 while((ch=getchar())>='0'&&ch<='9') re=re*10+ch-'0'; 15 return flag?-re:re; 16 } 17 18 struct edge{ 19 int to,nxt,cap; 20 edge(int to=0,int nxt=0,int cap=0): 21 to(to),nxt(nxt),cap(cap){} 22 }; 23 24 const int maxn=10005,maxm=100005; 25 26 int n,m,s,t,cnt=1; 27 int tou[maxn],head[maxn],q[maxn],d[maxn]; 28 edge edges[maxm<<1]; 29 30 //增加一条流量为c的正向边和流量为0的反向边 31 //利于记录边的流量状态 32 inline void add_edge(int from,int to,int c){ 33 edges[++cnt]=edge(to,head[from],c); 34 head[from]=cnt; 35 edges[++cnt]=edge(from,head[to],0); 36 head[to]=cnt; 37 } 38 39 void init(){ 40 n=read(); m=read(); s=read(); t=read(); 41 for(int i=0,from,to,c;i<m;i++){ 42 from=read(); to=read(); c=read(); 43 add_edge(from,to,c); 44 } 45 } 46 47 //寻找增广路 48 bool bfs(){ 49 memset(d,-1,(n+1)<<2); 50 d[t]=0; q[1]=t; 51 int hh=1,tt=2; 52 while(hh!=tt){ 53 int cur=q[hh++]; 54 for(int e=head[cur];e;e=edges[e].nxt){ 55 int curto=edges[e].to; 56 if(d[curto]==-1&&edges[e^1].cap){ 57 //printf("%d\n",curto); 58 d[curto]=d[cur]+1; 59 q[tt++]=curto; 60 //找到一条边就返回,玄学优化? 61 if(curto==s) return 1; 62 } 63 } 64 } 65 //没有玄学优化的写法,有了玄学优化是不是该return 0? 66 return d[s]!=-1; 67 } 68 69 int dfs(int x,int f){ 70 if(f<=0) return 0; 71 if(x==t) return f; 72 int ca=0; 73 //神秘的当前弧优化 74 for(int& e=head[x];e;e=edges[e].nxt){ 75 int curto=edges[e].to; 76 //并不是之前的dfs()中找到的增广路啊 77 if(d[curto]+1!=d[x]) continue; 78 //利用限制流量 79 int w=dfs(curto,(edges[e].cap<f-ca)?edges[e].cap:(f-ca)); 80 //直接对路的流量进行修改 81 edges[e].cap-=w; edges[e^1].cap+=w; ca+=w; 82 //已达到了限制流量 83 if(ca==f) break; 84 } 85 //已经gg的寻找 86 if(!ca) d[x]=-1; 87 return ca; 88 } 89 90 int dinic(){ 91 int ans=0; 92 //****当前弧优化的必要操作 93 memcpy(tou,head,(n+1)<<2); 94 while(bfs()){ 95 ans+=dfs(s,inf); 96 memcpy(head,tou,(n+1)<<2); 97 } 98 return ans; 99 } 100 101 int main(){ 102 //freopen("temp.in","r",stdin); 103 init(); 104 printf("%d\n",dinic()); 105 return 0; 106 }
亲测表现良好。。。