ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

网络流在残量网络上的改图操作

2021-11-12 13:01:18  阅读:121  来源: 互联网

标签:int ll 残量 网络 addflow edge 改图 include dis


Q: 网络流如果第一题和第二题就差少数边不一样,就比如说本来(1,2)容量为1,第二问(1,2)容量变成INF,这种情况可以直接在(1,2)间加一条边继续增广来求吗?
A: 可以 就加到残量网络上 就行了

那么费用流可以吗?
我觉得在最大流不变,费用改变的情况下是不可以的,因为

inline ll Dinic(int on) {
    ll res = 0, cost = 0;
    while (spfa(on)) {
        ll flow = dfs(S, inf);
        res += flow, cost += flow * dis[T];
    }
    return cost;
}

发现 \(flow\) 为 \(0\) 时,这里一乘,诶,没了

至于有没有更优美的写法,最近再思考思考这个问题

用一个简便的例子演示一下加到残量网络的操作

int main() {
    memset(head, -1, sizeof head);
    int n;
    S = 10, T = 11;
    add(S, 1, 1);
    add(S, 2, 1);

    add(1, 3, 1);
    add(2, 3, 1);

    add(3, T, 1);
    int m = cnt_edge - 2;
    cout << e[m].v << endl;
    
    cout << dinic() << endl;
    e[m].w = INF;
    cout << dinic() << endl;
}

输出

11
1
1

一开始流量为1,加边后又增广1,如果是统计答案记得要求和,因为每次Dinic返回的是本次增广多出来的流

对于费用流也同样:

signed main() {
    
    S = 10, T = 11;
    addflow(S, 1, 1, 1);
    addflow(S, 2, 1, 2);

    addflow(1, 3, 1, 1);
    addflow(2, 3, 1, 2);

    addflow(3, T, 1, 1);
    int m = cnt_edge - 1;
    cout << m << " " << e[m].to << endl;

    cout << Dinic(-1) << endl;
    e[m].flow = 0x3f3f3f3f;
    cout << Dinic(-1) << endl;
}

写的是最大费用流,于是先增广了费用高的那一条,第二次增广了费用小的那一条,因此
output

5
3

最大流完整代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 500 + 5;
const int M = N;
const int INF = 0x3f3f3f3f;
struct edge {
    int v, w, to;
} e[M * 2];
int pre[N], cnt_edge, dep[N];
int S, T, z, head[N], sum;
int n, m, q[N], cur[N];
void add(int u, int v, int w) {
    e[cnt_edge] = {v, w, head[u]};
    head[u] = cnt_edge++;
    e[cnt_edge] = {u, 0, head[v]};
    head[v] = cnt_edge++;
}
bool bfs() {
    for (int i = 0; i <= T; i++) dep[i] = 0;
    dep[S] = 1;
    int l = 0, r = 1;
    q[r] = S;
    while (l < r) {
        int u = q[++l];
        for (int i = head[u]; i != -1; i = e[i].to) {
            int v = e[i].v;
            if (!dep[v] && e[i].w) dep[v] = dep[u] + 1, q[++r] = v;
        }
    }
    return dep[T];
}
int dfs(int u, int mi) {
    int res = 0;
    if (mi == 0 || u == T) return mi;
    for (int &i = cur[u]; i != -1; i = e[i].to) {
        int v = e[i].v;
        if (dep[u] + 1 == dep[v] && e[i].w) {
            int minn = dfs(v, min(mi - res, e[i].w));
            e[i].w -= minn;
            e[i ^ 1].w += minn;
            res += minn;
            if (res == mi) return res;
        }
    }
    if (res == 0) dep[u] = 0;
    return res;
}
int dinic() {
    ll res = 0;
    while (bfs()) {
        memcpy(cur, head, sizeof(head));
        //    cout<<res<<endl;
        res += dfs(S, INF);
    }
    return res;
}
int main() {
    memset(head, -1, sizeof head);
    int n;
    S = 10, T = 11;
    add(S, 1, 1);
    add(S, 2, 1);

    add(1, 3, 1);
    add(2, 3, 1);

    add(3, T, 1);
    int m = cnt_edge - 2;
    cout << e[m].v << endl;
    
    cout << dinic() << endl;
    e[m].w = INF;
    cout << dinic() << endl;
}
费用流完整代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#define endl '\n'
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define P pair<int, int>
using namespace std;

#define int long long
typedef long long ll;
const int maxn = 20 * 40 * 2 * 2 + 5;
const ll inf = 1e18;
int n1, n2, cnt_edge = 1, S, T;
int a1[maxn], a2[maxn], head[maxn];
ll dis[maxn];
bool vis[maxn];
struct edge {
    int to, nxt;
    ll flow, cost;
} e[(maxn * maxn) << 2];
inline void add(int u, int v, ll w, ll c) {
    e[++cnt_edge].nxt = head[u];
    head[u] = cnt_edge;
    e[cnt_edge].to = v;
    e[cnt_edge].flow = w;
    e[cnt_edge].cost = c;
}
inline void addflow(int u, int v, ll w, ll c) {
    add(u, v, w, c);
    add(v, u, 0, -c);
    // if(u + 1 == v)
    // cout << "add: "<<u << " " << v << " "<<cnt_edge<<endl;
}
inline bool spfa(int on) {
    memset(vis, 0, sizeof(vis));
    if (on == 1)
        for (int i = 0; i <= T; i++) dis[i] = inf;
    else
        for (int i = 0; i <= T; i++) dis[i] = -inf;

    queue<int> q;
    q.push(S);
    dis[S] = 0;
    vis[S] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for (int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            // cout << "->" << y << endl;
            if ((on == 1 && e[i].flow && dis[y] > dis[x] + e[i].cost) ||
                (on == -1 && e[i].flow && dis[y] < dis[x] + e[i].cost)) {
                dis[y] = dis[x] + e[i].cost;
                if (!vis[y]) q.push(y), vis[y] = 1;
            }
        }
    }
    if (on == 1)
        return dis[T] != inf;
    else
        return dis[T] != -inf;
}
ll dfs(int x, ll lim) {
    vis[x] = 1;
    if (x == T || lim <= 0) return lim;
    ll res = lim;
    for (int i = head[x]; i; i = e[i].nxt) {
        int y = e[i].to;
        if (dis[y] != dis[x] + e[i].cost || e[i].flow <= 0 || vis[y]) continue;
        ll tmp = dfs(y, min(res, e[i].flow));
        res -= tmp;
        e[i].flow -= tmp;
        e[i ^ 1].flow += tmp;
        if (res <= 0) break;
    }
    return lim - res;
}
inline ll Dinic(int on) {
    ll res = 0, cost = 0;
    while (spfa(on)) {
        ll flow = dfs(S, inf);
        res += flow, cost += flow * dis[T];
        // cout << "flow " << flow << " " << dis[T] << endl;
    }
    return cost;
}
int val[maxn][maxn];
int id(int x, int y, int in) {
    return 2 * ((n1 * 2 + x - 2) * (x - 1) / 2 + y - 1) + in;
}
vector<int> edge[3];
//拆点之间的边
//除S T 的相邻的边
// T相邻边

struct debug { int u, v, id1, id2; };
signed main() {
    
    S = 10, T = 11;
    addflow(S, 1, 1, 1);
    addflow(S, 2, 1, 2);

    addflow(1, 3, 1, 1);
    addflow(2, 3, 1, 2);

    addflow(3, T, 1, 1);
    int m = cnt_edge - 1;
    // cout << m << " " << e[m].to << endl;

    cout << Dinic(-1) << endl;
    e[m].flow = 0x3f3f3f3f;
    cout << Dinic(-1) << endl;
    return 0;
}

标签:int,ll,残量,网络,addflow,edge,改图,include,dis
来源: https://www.cnblogs.com/FushimiYuki/p/15544036.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有