zoukankan      html  css  js  c++  java
  • 最大流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
    ",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
    ",dinic());
    105     return 0;
    106 }

    亲测表现良好。。。

  • 相关阅读:
    BZOJ 1101 莫比乌斯函数+分块
    BZOJ 2045 容斥原理
    BZOJ 4636 (动态开节点)线段树
    BZOJ 2005 容斥原理
    BZOJ 2190 欧拉函数
    BZOJ 2818 欧拉函数
    BZOJ 3123 主席树 启发式合并
    812. Largest Triangle Area
    805. Split Array With Same Average
    794. Valid Tic-Tac-Toe State
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/7231058.html
Copyright © 2011-2022 走看看