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 }

    亲测表现良好。。。

  • 相关阅读:
    事务的隔离级别
    事务的隔离
    事务简介
    leetcode647
    leetcode394
    leetcode96
    leetcode814
    leetcode738
    leetcode621
    leetcode763
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/7231058.html
Copyright © 2011-2022 走看看