模板_网络流

来源:互联网 发布:免费换ip软件 编辑:程序博客网 时间:2024/04/30 05:52

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

#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<climits>#include<iostream>using namespace std;#define N 205struct 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*2struct 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*2struct 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;
1 0
原创粉丝点击