網絡流模板彙總

很棒的最小割模型論文(手動置頂)

論文鏈接

Dinic

interger型
#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<<endl
#define see(x) cerr<<(#x)<<'='<<(x)<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}

const int maxn = 1e5+7;
const int maxm = 3e5+7;
const int inf = 0x3f3f3f3f;

int head[maxn], to[maxm], w[maxm], nxt[maxm], tot=1;
int cur[maxn], level[maxn];

void add_edge(int u, int v, int c) {
    ++tot; to[tot]=v; w[tot]=c; nxt[tot]=head[u]; head[u]=tot;
    ++tot; to[tot]=u; w[tot]=0; nxt[tot]=head[v]; head[v]=tot;
}

bool bfs(int s, int t) {
    memset(level,0,sizeof(level));
    queue<int> q;
    level[s]=1;
    q.push(s);
    while(!q.empty()) {
        int u=q.front(); q.pop();
        for(int i=head[u]; i; i=nxt[i]) {
            int v=to[i];
            if(!w[i]||level[v]) continue;
            level[v]=level[u]+1;
            q.push(v);
        }
    }
    return level[t];
}

int dfs(int u, int t, int flow) {
    if(u==t||flow==0) return flow;
    int f, ret=0;
    for(int &i=cur[u]; i; i=nxt[i]) {
        int v=to[i];
        if(level[v]==level[u]+1&&(f=dfs(v,t,min(flow,w[i])))>0) {
            w[i]-=f; w[i^1]+=f;
            flow-=f; ret+=f;
            if(!flow)break;
        }
    }
    if(!ret) level[u]=0;
    return ret;
}

int dinic(int s, int t) {
    int ret=0;
    while(bfs(s,t)) memcpy(cur,head,sizeof(cur)), ret+=dfs(s,t,inf);
    return ret;
}

int main() {
    int n=read(), m=read(), s=read(), t=read();
    for(int i=1; i<=m; ++i) {
        int u=read(), v=read(), w=read();
        add_edge(u,v,w);
    }
    printf("%d\n", dinic(s,t));
}
double型
#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<<endl
#define see(x) cerr<<(#x)<<'='<<(x)<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}

const int maxn = 1e5+7;
const int maxm = 3e5+7;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;

int head[maxn], to[maxm], nxt[maxm], tot=1;
double w[maxm];
int cur[maxn], level[maxn];

void add_edge(int u, int v, double c) {
    ++tot; to[tot]=v; w[tot]=c; nxt[tot]=head[u]; head[u]=tot;
    ++tot; to[tot]=u; w[tot]=0; nxt[tot]=head[v]; head[v]=tot;
}

bool bfs(int s, int t) {
    memset(level,0,sizeof(level));
    queue<int> q;
    level[s]=1;
    q.push(s);
    while(!q.empty()) {
        int u=q.front(); q.pop();
        for(int i=head[u]; i; i=nxt[i]) {
            int v=to[i];
            if(fabs(w[i])<=eps||level[v]) continue;
            level[v]=level[u]+1;
            q.push(v);
        }
    }
    return level[t];
}

double dfs(int u, int t, double flow) {
    if(u==t||fabs(flow)==0) return flow;
    double f, ret=0;
    for(int &i=cur[u]; i; i=nxt[i]) {
        int v=to[i];
        if(level[v]==level[u]+1&&(f=dfs(v,t,min(flow,w[i])))>=eps) {
            w[i]-=f; w[i^1]+=f;
            flow-=f; ret+=f;
            if(fabs(flow)<=eps)break;
        }
    }
    if(fabs(ret)<=eps) level[u]=0;
    return ret;
}

double dinic(int s, int t) {
    double ret=0;
    while(bfs(s,t)) memcpy(cur,head,sizeof(cur)), ret+=dfs(s,t,5e18);
    return ret;
}

int main() {
    int n=read(), m=read(), s=read(), t=read();
    for(int i=1; i<=m; ++i) {
        int u=read(), v=read();
        double w; scanf("%lf", &w);
        add_edge(u,v,w);
    }
    printf("%.3f\n", dinic(s,t));
}

費用流

#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<<endl
#define see(x) cerr<<(#x)<<'='<<(x)<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}

const int maxn = 2e4+7;
const int maxm = 2e5+7;
const int inf = 0x3f3f3f3f;

ll maxflow, mincost;
int last[maxn], pre[maxn], dis[maxn], now[maxn];
int head[maxn], to[maxm], flow[maxm], cost[maxm], nxt[maxm], tot=1;
bool inq[maxn];

void add_edge(int u,int v,int f,int c) {
    ++tot; to[tot]=v; flow[tot]=f; cost[tot]=c; nxt[tot]=head[u]; head[u]=tot;
    ++tot; to[tot]=u; flow[tot]=0; cost[tot]=-c; nxt[tot]=head[v]; head[v]=tot;
}

void init() { tot=1; memset(head,0,sizeof(head)); mincost=maxflow=0; }

bool spfa(int s, int t) {
    memset(dis,inf,sizeof(dis));
    memset(now,inf,sizeof(now));
    memset(inq,0,sizeof(inq));
    queue<int> q;
    dis[s]=0; pre[t]=-1; q.push(s); inq[s]=1;
    while(!q.empty()) {
        int u=q.front(); q.pop(); inq[u]=0;
        for(int i=head[u]; i; i=nxt[i]) {
            int v=to[i];
            if(flow[i]>0&&dis[v]>dis[u]+cost[i]) {
                dis[v]=dis[u]+cost[i];
                now[v]=min(now[u],flow[i]);
                last[v]=i; pre[v]=u;
                if(!inq[v]) q.push(v), inq[v]=1;
            }
        }
    }
    return pre[t]!=-1;
}

void MCMF(int s, int t) {
    while(spfa(s,t)) {
        int u=t;
        maxflow+=now[t];
        mincost+=now[t]*ll(dis[t]);
        while(u!=s) {
            flow[last[u]]-=now[t];
            flow[last[u]^1]+=now[t];
            u=pre[u];
        }
    }
}

int main() {
    int n=read(), m=read(), s=read(), t=read();
    for(int i=1; i<=m; ++i) {
        int u=read(), v=read(), w=read(), f=read();
        add_edge(u,v,w,f);
    }
    MCMF(s,t);
    printf("%lld %lld\n", maxflow, mincost);
}

最大權閉合子圖

閉合圖(針對有向圖):圖中點集的出邊也在點集中。(相當於有向邊終點是有向邊起點的必要條件)

最大權閉合子圖:圖中每個點有點權,則權值最大的閉合子圖爲最大權閉合子圖。

原閉合圖構造:額外加入源點 ss ,匯點 tt ,與 ss 相連的點( SS )的點權都爲正,與 tt 相連的點( TT )的點權都爲負(0就隨意啦),這兩者的邊權用點權(取絕對值)代替; SSTT 的連邊邊權爲無窮。

最大權閉合子圖權值爲:SW\displaystyle \sum{S}-WWW爲閉合圖的最小割 )

(由於 <S,T><S,T> 都是無窮邊,因此最小割一定是簡單割,即所有割邊都與源點或匯點相連)

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