【網路流各種模板】

來源:互聯網
上載者:User

EK 複雜度O(V*E*E)

#define N 204    int c[N][N];//邊容量  int f[N][N];//邊實際流量  int pre[N];//記錄增廣路徑  int res[N];//殘餘網路  queue<int> qq;  void init(){      while(!qq.empty())qq.pop();      memset(c,0,sizeof(c));      memset(f,0,sizeof(f));  }  int EK(int s,int t){      int i,j;      int ans=0;      while(1){          memset(res,0,sizeof(res));          res[s] = MAX;//源點的殘留網路要置為無限大!否則下面找增廣路出錯          pre[s] = -1;          qq.push(s);          //bfs找增廣路徑          while(!qq.empty()){              int x = qq.front();              qq.pop();              for(i=1;i<=t;i++){                  if(!res[i] && f[x][i] < c[x][i]){                      qq.push(i);                      pre[i] = x;                      res[i] = min(c[x][i] - f[x][i], res[x]);//這裡類似dp,如果有增廣路,那麼res[t]就是增廣路的最小權                  }              }          }          if(res[t]==0)break;//找不到增廣路就退出          int k = t;          while(pre[k]!=-1){              f[pre[k]][k] += res[t];//正向邊加上新的流量              f[k][pre[k]] -= res[t];//反向邊要減去新的流量,反向邊的作用是給程式一個後悔的機會              k = pre[k];          }          ans += res[t];      }      return ans;  }  

Dinic遞迴(推薦)

#define M 400    struct node {      int u, v, next, cap;  } edge[M*M];  int next[M], head[M], layer[M], Q[M * 2], mark[M];  int ecnt;  void init(){      ecnt= 0;      memset(head,-1,sizeof(head));  }  void add(int u, int v, int c) {      edge[ecnt].u = u;      edge[ecnt].v = v;      edge[ecnt].cap = c;      edge[ecnt].next = head[u];      head[u] = ecnt++;        edge[ecnt].u = v;      edge[ecnt].v = u;      edge[ecnt].cap = 0;      edge[ecnt].next = head[v];      head[v] = ecnt++;  }    bool BFS(int begin, int end) {      int i, l, h, k, y;      for (i = 0; i <= end; i++) layer[i] = -1;      layer[begin] = 0;      l = h = 0;      Q[l++] = begin;      while (h < l) {          k = Q[h++];          for (i = head[k]; i != -1; i = edge[i].next) {              y = edge[i].v;              if (edge[i].cap > 0 && layer[y] == -1) {                  layer[y] = layer[k] + 1;                  if (y == end)                      return true;                  Q[l++] = y;              }          }      }      return false;  }    int DFS(int x, int exp, int end) {      mark[x] = 1;      if (x == end)return exp;      int y, temp, i;      for (i = next[x]; i != -1; i = edge[i].next, next[x] = i) {          y = edge[i].v;          if (edge[i].cap > 0 && layer[y] == layer[x] + 1 && !mark[y]) {              if ((temp = (DFS(y, min(exp, edge[i].cap), end))) > 0) {                  edge[i].cap -= temp;//流完後正向流表示剩餘流量                  edge[i^1].cap += temp;//流完後反向流表示正向流的流量                  return temp;              }          }      }      return 0;  }    int Dinic_flow(int begin, int end) {      int i, ans = 0, flow;      while (BFS(begin, end)) {          for (i = 0; i <= end; i++)next[i] = head[i];          while (true) {              for (i = 0; i <= end; i++) mark[i] = 0;              flow = DFS(begin, INT_MAX, end);              if (flow == 0)break;              ans += flow;          }      }      return ans;  }  

Dinic非遞迴 複雜度O(V^2*E)

#define N 20100#define sta que//靜態鄰接表int level[N];int p[N],p1[N];int ecnt;int que[N];int n,m;struct edge{    int v,next;    int c;}e[900000];void init(){    ecnt = 0;    memset(p,-1,sizeof(p));}void insert(int u,int v,int c,int w){    e[ecnt].v = v;    e[ecnt].c = c;    e[ecnt].next = p[u];    p[u] = ecnt++;    e[ecnt].v = u;    e[ecnt].c = w;    e[ecnt].next = p[v];    p[v] = ecnt++;}int Dinic(int st,int ed){    int ans = 0;    int i,u,v,c;    int head,rear,top;    while(1){//重建層次圖        memset(level,0,sizeof(level));        head = rear = 0;        level[st]=1;        que[rear++]=st;        while(head<rear){            u = que[head++];            for(i=p[u];i!=-1;i=e[i].next){                v = e[i].v;                c = e[i].c;                if(c && level[v] == 0){                    level[v] = level[u]+1;                    que[rear++]=v;                }            }        }        if(level[ed] == 0){//無增廣路            break;        }        memcpy(p1,p,sizeof(p1));        top = -1;        while(1){            if(top<0){                for(i=p1[st];i!=-1;i=e[i].next){                    v = e[i].v;                    c = e[i].c;                    if(c && p1[v] != -1 && level[v] == 2)break;                }                if(i>=0){                    sta[++top] = i;                    p1[st] = e[i].next;                } else break;            }            u = e[sta[top]].v;            if(u == ed){//找到一條增廣路//計算流的可改進量,並記錄離源點最遠的可能會組成下一條增廣路徑的邊                int dd = MAX,index = -1;                for(i=0;i<=top;i++){                    if(dd>e[sta[i]].c){                        dd = e[sta[i]].c;                        index = i;                    }                }                ans += dd;                //調整殘餘網路                for(i=0;i<=top;i++){                    //直接由上一殘餘網路計算當前殘餘網路 見導論P401                    e[sta[i]].c -= dd;                    e[sta[i]^1].c += dd;                }                //回溯到路徑上某個可能繼續增廣的頂點,若該頂點也無法增廣,則回溯到前一個頂點(1)                for(i=0;i<=top;i++){                    if(e[sta[i]].c==0){                        top = index-1;                        break;                    }                }            } else {                for(i=p1[u];i!=-1;i = e[i].next){                    v = e[i].v;                    c = e[i].c;                    if(c && p1[v]!=-1 && level[u]+1 == level[v])break;                }                if(i!=-1){                    sta[++top] = i;                    p1[u] = e[i].next;//若沿著邊i找到了增廣路,則p1會被從新初始化;否則斷定從邊i出發無法到達匯點,以後搜尋增廣路將不再考慮此邊。估可將其忽略                } else {                    p1[u] = -1;                    top--;                }            }        }    }    return ans;}

SAP非遞迴  複雜度O(V*V*E)

#define N 440  #define M N*N  #define inf 1<<30int head[N];  struct Edge  {      int v,next,c;  }edge[M];  int ecnt;  void init(){      ecnt = 0;      memset(head,-1,sizeof(head));  }  void add(int u,int v,int w) {      edge[ecnt].v=v;      edge[ecnt].c=w;      edge[ecnt].next=head[u];      head[u]=ecnt++;      edge[ecnt].v=u;      edge[ecnt].c=0;      edge[ecnt].next=head[v];      head[v]=ecnt++;  }  int sap(int s,int t,int nodenum){ //源,匯,匯點編號(非點數)      int pre[N],cur[N],dis[N],gap[N];      int flow=0,aug=inf;      int u;      bool flag;      int i,j;      for(i=0;i<=nodenum;i++){              cur[i]=head[i];              gap[i]=dis[i]=0;      }      gap[s]=nodenum;      u=pre[s]=s;      while(dis[s]<nodenum){          flag=0;          for(j=cur[u];j!=-1;j=edge[j].next){                  int v=edge[j].v;                  if(edge[j].c>0 && dis[u]==dis[v]+1){                      flag=1;                      cur[u] = j;                      aug = min(aug,edge[j].c);                      pre[v]=u;                      u=v;                      if(u==t){                          flow+=aug;                          while(u!=s){                                u=pre[u];                              edge[cur[u]].c -= aug;    //邊的正流不斷減少                             edge[cur[u]^1].c += aug;  //反流增加                        }                          aug=inf;                      }                      break;                  }          }          if(flag)continue;          if(--gap[dis[u]] == 0)break;          for(dis[u] = nodenum, j=head[u]; j!=-1; j=edge[j].next){              int v=edge[j].v;              if(edge[j].c>0 && dis[v]<dis[u]){                  dis[u]=dis[v];                  cur[u]=j;              }          }          dis[u]++;          gap[dis[u]]++;          u=pre[u];      }      return flow;  }  

ISAP + GAP最佳化 複雜度O(V^2*E)

#define N 20010 #define M 500010int n,m;//n為點數 m為邊數  int h[N];  int gap[N];  int p[N],ecnt;  int source,sink;  struct edge{      int v;      int next;//下一條邊的編號      int val;//邊權值  }e[M];    inline void init(){memset(p,-1,sizeof(p));ecnt=0;}     //有向  inline void add1(int from,int to,int val){      e[ecnt].v=to;      e[ecnt].val=val;      e[ecnt].next=p[from];      p[from]=ecnt++;         swap(from,to);         e[ecnt].v=to;      e[ecnt].val=0;      e[ecnt].next=p[from];      p[from]=ecnt++;  }     //無向  inline void add2(int from,int to,int val){      e[ecnt].v=to;      e[ecnt].val=val;      e[ecnt].next=p[from];      p[from]=ecnt++;        swap(from,to);         e[ecnt].v=to;      e[ecnt].val=val;      e[ecnt].next=p[from];      p[from]=ecnt++;  }       inline int dfs(int pos,int cost){      if (pos==sink){          return cost;      }      int j,minh=n-1,lv=cost,d;      for (j=p[pos];j!=-1;j=e[j].next){          int v=e[j].v,val=e[j].val;          if(val>0){              if (h[v]+1==h[pos]){                  if (lv<e[j].val) d=lv;                  else d=e[j].val;                     d=dfs(v,d);                  e[j].val-=d;                  e[j^1].val+=d;                  lv-=d;                  if (h[source]>=n) return cost-lv;                  if (lv==0) break;              }                 if (h[v]<minh)   minh=h[v];          }      }      if (lv==cost){          --gap[h[pos]];          if (gap[h[pos]]==0) h[source]=n;          h[pos]=minh+1;          ++gap[h[pos]];      }      return cost-lv;  }     int sap(int st,int ed){      source=st;      sink=ed;      int ans=0;      memset(gap,0,sizeof(gap));      memset(h,0,sizeof(h));      gap[st]=n;      while (h[st]<n){          ans+=dfs(st,INT_MAX);      }      return ans;  }  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.