最大流ISAP+Dinic

来源:互联网 发布:java 字符串反转 编辑:程序博客网 时间:2024/05/17 01:01

快速最大流ISAP模板

//By kuangbin//只能求一次最大流#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>const int MAXN=20010;const int MAXM=440020;//注意边的数目,因为连边是连两条/经常reconst int INF=0x3f3f3f3f;using namespace std;//int n,s,t,N;//输入的顶点数,源点,汇点,总顶点数struct Edge {    int to,next,cap,flow;} edge[MAXM<<1];int head[MAXN],tot,gap[MAXN],d[MAXN],cur[MAXN],que[MAXN],p[MAXN];void init(){    tot=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int c){    edge[tot].to = v;    edge[tot].cap = c;    edge[tot].flow = 0;    edge[tot].next = head[u];    head[u] = tot++;    edge[tot].to = u;    edge[tot].cap = 0;    edge[tot].flow = 0;    edge[tot].next = head[v];    head[v] = tot++;}void BFS(int source,int sink){    memset(d,-1,sizeof(d));//clr(d,-1);    memset(gap,0,sizeof(gap));//clr(gap,0);    gap[0] = 1;    int front = 0,rear = 0;    d[sink] = 0;    que[rear++] = sink;    while(front != rear) {        int u = que[front++];        for(int i = head[u]; i != -1; i = edge[i].next) {            int v = edge[i].to;            if(d[v] != -1) continue;            que[rear++] = v;            d[v] = d[u]+1;            gap[d[v]]++;        }    }}int isap(int source,int sink,int N){    BFS(source,sink);    memcpy(cur,head,sizeof(head));    int top = 0,x = source,flow = 0;    while(d[source] < N) {        if(x == sink) {            int Min = INF,inser;            for(int i = 0; i < top; ++i) {                if(Min > edge[p[i]].cap - edge[p[i]].flow) {                    Min = edge[p[i]].cap - edge[p[i]].flow;                    inser = i;                }            }            for(int i = 0; i < top; ++i) {                edge[p[i]].flow += Min;                edge[p[i]^1].flow -= Min;            }            flow += Min;            top = inser;            x = edge[p[top]^1].to;            continue;        }        int ok = 0;        for(int i = cur[x]; i != -1; i = edge[i].next) {            int v = edge[i].to;            if(edge[i].cap > edge[i].flow && d[v]+1 == d[x]) {                ok = 1;                cur[x] = i;                p[top++] = i;                x = edge[i].to;                break;            }        }        if(!ok) {            int Min = N;            for(int i = head[x]; i != -1; i = edge[i].next) {                if(edge[i].cap > edge[i].flow && d[edge[i].to] < Min) {                    Min = d[edge[i].to];                    cur[x] = i;                }            }            if(--gap[d[x]] == 0) break;            gap[d[x] = Min+1]++;            if(x != source) x = edge[p[--top]^1].to;        }    }    return flow;}

//这个模板有待商榷const int maxn= 405;//最大顶点数const int maxm = 160005;//最大边数const int INF=0x3f3f3f3f;using namespace std;int n,s,t,N;//输入的顶点数,源点,汇点,建图后的总顶点数(判断dis[s]<N)struct node{    int to,cap,next,pre;//pre是指互为反向弧}edges[maxm];int head[maxn],tot,que[maxn],d[maxn],gap[maxn],cur[maxn],rpath[maxn];//邻接表,边数,队列,距离标号,间隙优化,当前弧,可增广路上的弧编号void init(){    tot=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int c){    edges[tot].to=v;    edges[tot].cap=c;    edges[tot].next=head[u];    head[u] = tot ++;    edges[tot-1].pre=tot;    edges[tot].pre = tot-1;    edges[tot].cap = 0;    edges[tot].to = u;    edges[tot].next = head[v];    head[v] = tot ++;}void re_Bfs(){    memset(gap,0,sizeof(gap));    memset(d,-1,sizeof(d));    int i,front=0,rear=0;    que[rear ++] = t;    gap[0] = 1;    d[t] = 0;    while(front != rear){        int u = que[front ++];        for(i = head[u];i != -1;i = edges[i].next){            if(edges[edges[i].pre].cap == 0 || d[edges[i].to]!=-1)                continue;            d[edges[i].to] = d[u] + 1;            gap[d[edges[i].to]] ++;            que[rear ++] = edges[i].to;        }    }}int ISAP(){    re_Bfs();    memcpy(cur,head,sizeof(head));    int i,u=s,maxflow = 0;    while(d[s] < N){        if(u == t){            int curflow = INF;            for(i = s;i != t;i = edges[cur[i]].to)                curflow = min(curflow,edges[cur[i]].cap);            for(i = s;i != t;i = edges[cur[i]].to){                edges[cur[i]].cap -= curflow;                edges[edges[cur[i]].pre].cap += curflow;            }            maxflow += curflow;            u = s;        }        for(i = cur[u];i != -1;i = edges[i].next)            if(edges[i].cap > 0 && d[edges[i].to] + 1 == d[u])                break;        if(i != -1){            cur[u] = i;            rpath[edges[i].to] = edges[i].pre;            u = edges[i].to;        }        else{            if((-- gap[d[u]]) == 0) break;            cur[u] = head[u];            int Min = N;            for(i = cur[u];i != -1;i = edges[i].next)                if(edges[i].cap > 0)                    Min = min(Min,d[edges[i].to]);            gap[d[u]=Min+1] ++;            if(u != s) u = edges[rpath[u]].to;        }    }    return maxflow;}

Isap//速度好慢的

//注意给源点,汇点,结点总个数n 赋值,最大距离标号的修改#include<iostream>#include<cstring>#include<cstdio>#include<vector>const int maxn=210;//最大结点数const int INF=0x3f3f3f3f;using namespace std;int n,s,t,N;//输入的顶点数,源点,汇点,总顶点数struct Edge{    int from,to,cap,flow;    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}};vector<Edge> edges;//边集vector<int> G[maxn];//顶点集int gap[maxn],d[maxn],cur[maxn],p[maxn];//间隙优化,距离标号,当前弧,可增广路上的上一条弧inline void addedge(int u,int v,int c){    edges.push_back(Edge(u,v,c,0));    edges.push_back(Edge(v,u,0,0));    int m=edges.size();    G[u].push_back(m-2);    G[v].push_back(m-1);}int ISAP(int S,int T){    s=S,t=T;//别忘了赋值和修改    memset(cur,0,sizeof(cur));    memset(d,0,sizeof(d));    memset(gap,0,sizeof(gap));    int x=s,flow=0,a=INF;    while(d[s]<N){        if(x==t){            flow+=a;            while(x!=s){                edges[p[x]].flow+=a;                edges[p[x]^1].flow-=a;                x=edges[p[x]].from;            }            a=INF;        }        int ok=0;        for(int i=cur[x];i<G[x].size();++i){            Edge& e=edges[G[x][i]];            if(e.cap>e.flow&&d[e.to]+1==d[x]){                p[e.to]=G[x][i];                cur[x]=i;                x=e.to;                ok=1;                a=min(a,e.cap-e.flow);                break;            }        }        if(!ok){            int m=N;//为            for(int i=0;i<G[x].size();++i){                Edge& e =edges[G[x][i]];                if(e.cap>e.flow) m=min(m,d[e.to]);            }            if(--gap[d[x]]==0) break;            gap[d[x]=m+1]++;            cur[x]=0;            if(x!=s) x=edges[p[x]].from;        }    }    return flow;}

————————————————————————————
Dinic

#include<iostream>#include<cstring>#include<cstdio>#include<vector>#include<queue>const int maxn=1100;//最大顶点数const int maxm=1100;//最大边数const int INF=0x3f3f3f3f;//无穷大using namespace std;int n,m,s,t;//输入的顶点数,输入的边数,源点,汇点struct Edge{    int from,to,cap,flow;};vector<Edge> edges;//边集vector<int> G[maxn];//顶点集int d[maxn],cur[maxn];//距离标号,当前弧bool vis[maxn];//标记数组inline void addedge(int u,int v,int c){    edges.push_back((Edge){u,v,c,0});    edges.push_back((Edge){v,u,0,0});    int x=edges.size();    G[u].push_back(x-2);    G[v].push_back(x-1);}bool BFS(){//构建层次网络    memset(vis,0,sizeof(vis));    queue<int> Q;    Q.push(s);    d[s]=0;    vis[s]=1;    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(!vis[e.to]&&e.cap>e.flow){                vis[e.to]=1;                d[e.to]=d[x]+1;                Q.push(e.to);            }        }    }    return vis[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=edges[G[x][i]];        if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){            e.flow+=f;            edges[G[x][i]^1].flow-=f;            flow+=f;            a-=f;            if(a==0) break;        }    }return flow;}int Dinic(int S,int T){    s=S,t=T;    int flow=0;    while(BFS()){        memset(cur,0,sizeof(cur));        flow+=DFS(s,INF);    }    return flow;}
0 0
原创粉丝点击