最大流ISAP+Dinic

快速最大流ISAP模板

//By kuangbin
//只能求一次最大流
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

const int MAXN=20010;
const int MAXM=440020;//注意边的数目,因为连边是连两条/经常re
const 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;
}

你可能感兴趣的:(模板)