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

親測表現良好。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM