网络流算法

 

dinic 算法

 

时间复杂度 O(n*n*e) 

  1 struct node{
  2     int u,v,next,c;
  3 }edge[maxn<<1];
  4 int head[maxn];
  5 int cnt,dis[maxn],n,m,ans;
  6 
  7 void init(){
  8     memset(head,-1,sizeof(head));
  9     cnt=0;
 10     memset(dis,-1,sizeof(dis));
 11     ans=0;
 12 }
 13 void add(int a,int b,int c){
 14     edge[cnt].u=a;
 15     edge[cnt].v=b;
 16     edge[cnt].c=c;
 17     edge[cnt].next=head[a];
 18     head[a]=cnt++;
 19 }
 20 bool bfs(){
 21     memset(dis,-1,sizeof(dis));
 22     queue<int>q;
 23     dis[1]=0;
 24     q.push(1);
 25     int i,cur;
 26     while(!q.empty()) {
 27         cur=q.front();
 28         q.pop();
 29         for (int i=head[cur];i!=-1;i=edge[i].next){
 30             if(dis[edge[i].v]==-1&&edge[i].c>0){
 31                 dis[edge[i].v]=dis[cur]+1;
 32                 q.push(edge[i].v);
 33             }
 34         }
 35     }
 36     if(dis[m]<0) return 0;
 37     return 1;
 38 }
 39 int fnd(int x,int low){
 40     int a;
 41     if(x==m) return low;
 42     for (int i=head[x];i!=-1;i=edge[i].next){
 43         int v=edge[i].v;
 44         if(dis[v]==dis[x]+1&&edge[i].c>0&&(a=fnd(v,min(low,edge[i].c)))){
 45             edge[i].c-=a;
 46             edge[i^1].c+=a;
 47             return a;
 48         }
 49     }
 50     return 0;
 51 }
 52 void Dinic(){
 53     int temp;
 54     while(bfs()){
 55         temp=fnd(1,inf);
 56         ans+=temp;
 57     }
 58     printf("%d\n",ans);
 59 }
 60 
 61 各种优化:
 62 
 63 #include <iostream>  
 64 #include <cstdio>  
 65 #include <cstring>  
 66 #include <queue>  
 67 #define inf 0x3f3f3f3f3f3f3f3f  
 68 #define ll long long  
 69 #define MAXN 10005  
 70 using namespace std;  
 71 int n,m;//点数、边数   
 72 int sp,tp;//原点、汇点   
 73 struct node  
 74 {  
 75     int v,next;  
 76     ll cap;  
 77 }mp[MAXN*10];  
 78 int pre[MAXN],dis[MAXN],cur[MAXN];//cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表  
 79 int cnt=0;  
 80 void init()//不要忘记初始化  
 81 {  
 82     cnt=0;  
 83     memset(pre,-1,sizeof(pre));  
 84 }  
 85 void add(int u,int v,int w)//加边   
 86 {  
 87     mp[cnt].v=v;  
 88     mp[cnt].cap=w;  
 89     mp[cnt].next=pre[u];  
 90     pre[u]=cnt++;  
 91 }  
 92 bool bfs()//建分层图  
 93 {  
 94     memset(dis,-1,sizeof(dis));  
 95     queue<int>q;  
 96     while(!q.empty())  
 97     q.pop();  
 98     q.push(sp);  
 99     dis[sp]=0;  
100     int u,v;  
101     while(!q.empty())  
102     {  
103         u=q.front();  
104         q.pop();  
105         for(int i=pre[u];i!=-1;i=mp[i].next)  
106         {  
107             v=mp[i].v;  
108             if(dis[v]==-1&&mp[i].cap>0)  
109             {  
110                 dis[v]=dis[u]+1;  
111                 q.push(v);  
112                 if(v==tp)  
113                 break;  
114             }  
115         }  
116     }  
117     return dis[tp]!=-1;  
118 }  
119 ll dfs(int u,ll cap)//寻找增广路  
120 {  
121     if(u==tp||cap==0)  
122     return cap;  
123     ll res=0,f;  
124     for(int &i=cur[u];i!=-1;i=mp[i].next)  
125     {  
126         int v=mp[i].v;  
127         if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,mp[i].cap)))>0)  
128         {  
129             mp[i].cap-=f;  
130             mp[i^1].cap+=f;  
131             res+=f;  
132             if(res==cap)  
133             return cap;  
134         }  
135     }  
136     if(!res)  
137     dis[u]=-1;  
138     return res;  
139 }  
140 ll dinic()  
141 {  
142     ll ans=0;  
143     while(bfs())  
144     {  
145         for(int i=1;i<=n;i++)  
146         cur[i]=pre[i];  
147         ans+=dfs(sp,inf);  
148     }  
149     return ans;  
150 }  
151 int main()  
152 {  
153       
154 return 0;  
155 }
View Code

 

 当前弧优化:

#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <functional>  
#include <queue>  
#include <vector>  
using namespace std;  
const int maxn=1e5+10,inf=0x7fffffff;  
int n,m,f,e,s,t;  
struct Edge{  
    int u,v,c,flow;  
    Edge(int a,int b,int cc,int f):u(a),v(b),c(cc),flow(f){}  
};  
struct Dinic{  
    int s,t;  
    vector<Edge>edges;  
    vector<int>pre[maxn];  
    bool vis[maxn];  
    int dis[maxn];  
    int cur[maxn];  
    void init(){  
        for (int i=0;i<=n+1;i++)  
            pre[i].clear();  
        edges.clear();  
    }  
    void AddEdge(int a,int b,int c){  
        edges.push_back(Edge(a,b,c,0));  
        edges.push_back(Edge(b,a,0,0));  
        int mm=edges.size();  
        pre[a].push_back(mm-2);  
        pre[b].push_back(mm-1);  
    }  
    bool bfs(){  
        memset(vis,false,sizeof(vis));  
        queue<int>q;  
        q.push(s);  
        vis[s]=1;  
        dis[s]=0;  
        while(!q.empty()){  
            int  x=q.front();q.pop();  
        for (int i=0;i<pre[x].size();i++){  
            Edge &e=edges[pre[x][i]];  
            if(!vis[e.v]&& e.c>e.flow){  
                dis[e.v]=dis[x]+1;  
                vis[e.v]=1;  
                q.push(e.v);  
            }  
        }  
        }  
        return vis[t];  
    }  
    int dfs(int x,int cap){  
        if(x==t||cap==0) return cap;  
        int f,flow=0;  
        for (int &i=cur[x];i<pre[x].size();i++){  
            cur[x]=i;
            Edge &e=edges[pre[x][i]];  
            if(dis[e.v]==dis[x]+1 && (f=dfs(e.v,min(cap,e.c-e.flow)))){  
                e.flow+=f;  
                edges[pre[x][i]^1].flow-=f;  
                flow+=f;  
                cap-=f;  
                if(cap==0) break;  
            }  
        }  
        return flow;  
    }  
    int Maxflow(int s,int t){  
        this->s=s;  
        this->t=t;  
        int flow=0;  
        while(bfs()) {  
            memset(cur,0,sizeof(cur));  
            flow+=dfs(s,inf);  
        }  
        return flow;  
    }  
}dc;
View Code

 

EK算法模板 算法复杂度 n*m*m (n为点数,m为边数) 源点 1, 汇点 n。

const int maxn=310,inf=0x7fffffff;
int pre[maxn],mat[maxn][maxn];
bool vis[maxn];
int n,m;
int Augment(){
    int v;
    bool fnd=false;
    memset(pre,0,sizeof(pre));
    memset(vis,false,sizeof(vis));
    pre[1]=0;
    vis[1]=1;
    deque<int>q;
    q.push_back(1);
    while(!q.empty()){                 
        v=q.front();
        q.pop_front(); 
        for (int i=1;i<=m;i++){
            if(mat[v][i]>0&&!vis[i]){        //找到能走且为未走过的边
                vis[i]=1;
                pre[i]=v;
                if(i==m){
                    fnd=1;
                    q.clear();
                    break;
                }
                else q.push_back(i);
            }
        }
    }
    if(!fnd) return 0;
    v=m;
    int mi=inf;
    while(pre[v]){
        mi=min(mi,mat[pre[v]][v]);
        v=pre[v];
    }
    v=m;
    while(pre[v]){
        mat[pre[v]][v]-=mi;
        mat[v][pre[v]]+=mi;
        v=pre[v];
    }
    return mi;
}
View Code

 

 

参考博客:

https://blog.csdn.net/lxy767087094/article/details/53606891

https://blog.csdn.net/hitwhacmer1/article/details/47019789

http://acm.pku.edu.cn/summerschool/gw_netflow.pdf

http://www.cnblogs.com/jianrenfang/p/7253715.html

 

posted @ 2018-05-21 18:10  Acerkoo  阅读(228)  评论(0编辑  收藏  举报