模板_网络流

27 篇文章 0 订阅
23 篇文章 0 订阅

首先来一个简单的EdmondsKarp算法,跟SPFA很像,BFS找最短路

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<climits>
#include<iostream>
using namespace std;
#define N 205
struct Edge{
    int fr,to,cap,flow;
    Edge(int u,int v,int c,int f):fr(u),to(v),cap(c),flow(f){}
};
struct EdmondsKarp{
    int n,m;
    vector<Edge> edges;
    vector<int> G[N];
    int a[N],p[N];
    void init(int n){
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }
    void Add_Edge(int fr,int to,int cap){
        edges.push_back(Edge(fr,to,cap,0));
        edges.push_back(Edge(to,fr,0,0));
        m=edges.size();
        G[fr].push_back(m-2);
        G[to].push_back(m-1);
    }
    int Max_Flow(int s,int t){
        int flow=0;
        for(;;){
            memset(a,0,sizeof(a));
            queue<int> Q;
            Q.push(s);
            a[s]=INT_MAX;
            while(!Q.empty()){
                int x=Q.front();Q.pop();
                for(int i=0;i<G[x].size();i++){
                    Edge& e=edges[G[x][i]];
                    if(!a[e.to]&&e.cap>e.flow){
                        p[e.to]=G[x][i];
                        a[e.to]=min(a[x],e.cap-e.flow);
                        Q.push(e.to);
                    }
                }
                if(a[t]) break;
            }
            if(!a[t]) break;
            for(int u=t;u!=s;u=edges[p[u]].fr){
                edges[p[u]].flow+=a[t];
                edges[p[u]^1].flow-=a[t];
            }
            flow+=a[t];
        }
        return flow;
    }
}f;

唔……再来一个费用流吧
算法主体

    int spfa(){
        int s=hash(1,1)*2,t=hash(n,n)*2+1,x;
        queue<int> q;int b[N*N];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                d[hash(i,j)*2]=INF,b[hash(i,j)*2]=false;
                d[hash(i,j)*2+1]=INF,b[hash(i,j)*2+1]=false;
            }       
        b[s]=true,d[s]=0,a[s]=1;q.push(s);
        while(!q.empty()){
            x=q.front();q.pop();b[x]=false;
            for(int i=0;i<g[x].size();i++){
                Edge& e=edge[g[x][i]];
                if(e.cap>e.flow&&d[e.to]>d[x]+e.cost){
                    d[e.to]=d[x]+e.cost;
                    p[e.to]=g[x][i];
                    a[e.to]=min(a[x],e.cap-e.flow);
                    if(!b[e.to])    {b[e.to]=true;q.push(e.to);}
                }
            }
        }
        if(d[t]==INF) return 0;
        ans+=d[t]*a[t];
        for(x=t;x!=s;x=edge[p[x]].fr){
            edge[p[x]].flow+=a[t],edge[p[x]^1].flow-=a[t];
        }
        return 1;
    }

最大流的高效算法Dinic算法,BFS建层次图,DFS找增广路,递归算法

    bool bfs(){
        memset(d,-1,sizeof(d));memset(b,0,sizeof(b));
        queue<int> q;int x;d[S]=0;b[S]=true;q.push(S);
        while(!q.empty()){
            x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++){
                Edge &e=edge[g[x][i]];
                if(!b[e.to]&&e.cap>e.flow){
                    b[e.to]=true;d[e.to]=d[x]+1;q.push(e.to);
                }
            }
        }
        return b[T];
    }

    int dfs(int x,int a){
        if(x==T||a==0) return a;
        int flow=0,f;
        for(int &i=cur[x];i<g[x].size();i++){
            Edge &e=edge[g[x][i]];
            if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;edge[g[x][i]^1].flow-=f;
                flow+=f;a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }

    void Max_Flow(){
        flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow+=dfs(S,INF);
        }
    }

Dinic算法的非递归实现

    bool bfs(){
        memset(d,-1,sizeof(d));memset(b,0,sizeof(b));
        queue<int> q;int x;d[S]=0;b[S]=true;q.push(S);
        while(!q.empty()){
            x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++){
                Edge &e=edge[g[x][i]];
                if(!b[e.to]&&e.cap>e.flow){
                    b[e.to]=true;d[e.to]=d[x]+1;q.push(e.to);
                }
            }
        }
        return b[T];
    }
    void Max_Flow(){
        flow=0;
        while(bfs()){
            int k=0,x=S;
            memset(cur,0,sizeof(cur));
            for(;;){
                if(x==T){
                    int mine=-1,minf=INF;
                    for(int i=0;i<k;i++)
                        if(edge[p[i]].cap-edge[p[i]].flow<minf){
                            minf=edge[p[i]].cap-edge[p[i]].flow;
                            mine=i;
                        }
                    for(int i=0;i<k;i++){
                        edge[p[i]].flow+=minf;
                        edge[p[i]^1].flow-=minf;
                    }
                    k=mine;x=edge[p[mine]].fr;flow+=minf;
                }
                for(int &i=cur[x];i<g[x].size();i++){
                    Edge &e=edge[g[x][i]];
                    if(e.cap>e.flow&&d[x]+1==d[e.to]) break;
                }
                if(cur[x]<g[x].size()){
                    p[k++]=g[x][cur[x]];
                    x=edge[g[x][cur[x]]].to;
                }
                else{
                    if(k==0) break;
                    d[x]=-1;k--;x=edge[p[k]].fr;
                }
            }
        }
    }

最后比较神的算法,缩点全局最小割Stoer-Wagner

#include<cstdio>
#include<climits>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define N 505
#define INF INT_MAX/3*2
struct Min_Cut{
    struct Dist{
        int s,d;
    /*  Dist(int a,int b):s(a),d(b){}
        bool operator <(const Dist &b)const{
            if(d==b.d) return s>b.s;
            return d<b.d;
        }*/
    };
    int mp[N][N];bool use[N];
    int n,m,ans,S,T;


    int in(){
        int x=0;char ch=getchar();
        while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }

    void init(){
        memset(mp,0,sizeof(mp));memset(use,0,sizeof(use));
        int x,y,z;ans=INF;
        while(m--){
            x=in(),y=in(),z=in();
            mp[x][y]+=z;mp[y][x]+=z;
        }
        return;
    }

    int MinCut(int &s,int &t){
        bool vis[N];int w[N];
        memset(vis,0,sizeof(vis));memset(w,0,sizeof(w));
        int tmpj=N;
        for(int i=0;i<n;i++){
            int max=-INF;
            for(int j=0;j<n;j++){
                if(!vis[j]&&!use[j]&&max<w[j]){
                    max=w[j];
                    tmpj=j;
                }
            }
            if(t==tmpj){return w[t];}
            vis[tmpj]=1;
            s=t,t=tmpj;
            for(int j=0;j<n;j++){
                if(!vis[j]&&!use[j])
                    w[j]+=mp[t][j];
            }
        }
        return w[t];
    }

/*  int MinCut(int &S,int &T){
        priority_queue<Dist> q;queue<Dist> p;Dist t(0,0);
        for(int i=0;i<n;i++) 
            if(!use[i]) q.push(Dist(i,0));
        while(!q.empty()){
            t=q.top();q.pop();
            if(T==t.s){return t.d;}
            S=T;T=t.s;
            while(!q.empty()){
                p.push(q.top());q.pop();
            }
            while(!p.empty()){
                t=p.front();p.pop();
                q.push(Dist(t.s,mp[T][t.s]+t.d));
            }
        }
        return q.top().d;
    }*/

/*  
    Dist heap[N*2];int size;
    void push(Dist x){
        heap[++size]=x;
        int now,next;now=size,next=size/2;
        while(now>1){
            next=now/2;
            if(heap[next].d>heap[now].d) break;
            else swap(heap[next],heap[now]);
            now=next;
        }
        return;
    }

    Dist top(){
        Dist res=heap[1];heap[1]=heap[size--];
        int now,next;now=1;
        while(now*2<=size){
            next=now*2;
            if(next+1<=size&&heap[next].d>heap[next+1].d) next++;
            if(heap[now].d>heap[next].d)    break;
            swap(heap[now],heap[next]);
            now=next;
        }
        return res;
    }

    int MinCut(int &S,int &T){
        memset(heap,0,sizeof(heap));size=0;
        queue<Dist> p;Dist t;
        for(int i=0;i<n;i++) 
            if(!use[i]){
                t.s=i,t.d=0;
                push(t);
            }
        while(size){
            t=top();
            if(T==t.s){return t.d;}
            S=T;T=t.s;
            while(size)
                p.push(top());
            while(!p.empty()){
                t=p.front();p.pop();t.d+=mp[T][t.s];
                push(t);
            }
        }
        return top().d;
    }
    */

    void solve(){
        while(scanf("%d%d",&n,&m)!=EOF){
            init();
            for(int i=1;i<n;i++){
                S=T=-1;ans=min(ans,MinCut(S,T));use[T]=true;

                for(int j=0;j<n;j++){
                    mp[S][j]+=mp[T][j];
                    mp[j][S]+=mp[j][T];
                }
                /*for(int o=0;o<n;o++){
                    for(int u=0;u<n;u++){
                        printf("%d ",mp[o][u]);
                    }
                    printf("\n");
                }*/
//              printf("%d\n",ans);
            }
            printf("%d\n",ans);
        }
        return;
    }
}s;
int main(){
    s.solve();
    return 0;
}

最后才搞得ISAP

#include<cstdio>
#include<climits>
#include<cstring>
#include<queue>
#include<vector>
#include<iostream>
using namespace std;
#define N 505
#define INF INT_MAX/3*2
struct ISAP{
    struct Edge{int fr,to,flow,cap;};
    vector<Edge> edge;vector<int> g[N];
    int p[N],num[N],cur[N];int s,t,n;
    bool v[N];int d[N];

    void Add_Edge(int fr,int to,int flow,int cap){
        edge.push_back(Edge{fr,to,flow,cap});
        edge.push_back(Edge{to,fr,0,0});
        g[fr].push_back(edge.size()-2);g[to].push_back(edge.size()-1);
    }

    int AddFlow(){
        int x=t,a=INF;Edge e=edge[p[x]];
        for(;x!=s;x=edge[p[x]].fr,e=edge[p[x]]) a=min(e.cap-e.flow,a);
        x=t;
        for(;x!=s;x=edge[p[x]].fr) edge[p[x]].flow+=a,edge[p[x]^1].flow-=a;
        return a;
    }

    void BFS(){
        for(int i=0;i<n;i++) d[i]=n;
        memset(v,0,sizeof(v));
        queue<int> q;int x;q.push(t);v[t]=true,d[t]=0;
        while(!q.empty()){
            x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++){
                Edge &e=edge[g[x][i]];
                Edge &u=edge[g[x][i]^1];
                if(!v[e.to]&&u.cap>u.flow){
                    d[e.to]=d[x]+1;v[e.to]=true;
                    q.push(e.to);
                }
            }
        }
    }

    int MaxFlow(){
        int flow=0,x=s;BFS();
        memset(num,0,sizeof(num));memset(cur,0,sizeof(cur));
        for(int i=0;i<n;i++) num[d[i]]++;
        while(d[s]<n){
            if(x==t) flow+=AddFlow(),x=s;
            int ok=0;
            for(int i=cur[x];i<g[x].size();i++){
                Edge &e=edge[g[x][i]];
                if(e.cap>e.flow&&d[x]==d[e.to]+1){
                    ok=1;p[e.to]=g[x][i];
                    cur[x]=i;x=e.to;break;
                }
            }
            if(!ok){
                int m=n-1;
                for(int i=0;i<g[x].size();i++){
                    Edge &e=edge[g[x][i]];
                    if(e.cap>e.flow) m=min(m,d[e.to]);
                }
                if(!(--num[d[x]])) break;
                num[d[x]=m+1]++;cur[x]=0;
                if(x!=s) x=edge[p[x]].fr;
            }
        }
        return flow;
    }

}s;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值