【網絡流各種模板】

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<<30
int 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 500010
int 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;  
}  



























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章