最大流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 }

亲测表现良好。。。

 

posted @ 2017-07-24 21:02  ZYBGMZL  阅读(1984)  评论(1编辑  收藏  举报