网络流复习笔记

网络流的空间要好好算!!!

不然就各种出事。。。

混合图的欧拉回路

没有账号,懂个思路就好了

[POI2010]MOS-Bridges

看起来是前面那题多了个二分,待会去敲一敲

 

感觉自己最小割怎么跟没学过一样,摘了个oi-wiki上的模型

拍照

乍一看怎么和太空飞行计划一模一样

确实是一样的233

但怎么我之前会现在就连这个都不会了,药丸药丸

自闭了

文理分科

#include <bits/stdc++.h>

using namespace std;

const int N = 30010, M = 280010;

int n, m, a[110][110], s[110][110], sa[110][110], ss[110][110], id[110][110], tot, sum;

int head[N], to[M], nxt[M], edge[M], cnt = 1, st, ed, h[N];

void add_edge(int u, int v, int w) {
    to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt;
}

void addedge(int u, int v, int w) {
    add_edge(u, v, w), add_edge(v, u, 0);
}

queue<int> q; int d[N];

bool bfs() {
    while (q.size()) q.pop();
    for (int i = 0; i <= ed; i++) d[i] = 0, h[i] = head[i];
    q.push(st), d[st] = 1;
    while (q.size()) {
        int u = q.front(); q.pop();
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (edge[i] && !d[v]) {
                d[v] = d[u] + 1;
                if (v == ed) return true;
                q.push(v);
            }
        }
    }
    return false;
}

int dinic(int u, int flow) {
    if (u == ed) return flow;
    int rest = flow, now;
    for (int &i = h[u]; i; i = nxt[i]) {
        int v = to[i];
        if (edge[i] && d[v] == d[u] + 1) {
            now = dinic(v, min(edge[i], rest));
            //if (!now) d[v] = -1;
            edge[i] -= now, edge[i ^ 1] += now, rest -= now;
        }
    }
    return flow - rest;
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]), id[i][j] = ++tot, sum += a[i][j];
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) scanf("%d", &s[i][j]), sum += s[i][j];
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) scanf("%d", &sa[i][j]), sum += sa[i][j];
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) scanf("%d", &ss[i][j]), sum += ss[i][j];
    st = 0, ed = tot * 3 + 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            addedge(st, id[i][j], a[i][j]), addedge(id[i][j], ed, s[i][j]);
            int x = tot + id[i][j], y = x + tot;
            addedge(st, x, sa[i][j]), addedge(y, ed, ss[i][j]);
            addedge(x, id[i][j], 0x3f3f3f3f), addedge(id[i][j], y, 0x3f3f3f3f);
            if (i > 1) addedge(x, id[i - 1][j], 0x3f3f3f3f), addedge(id[i - 1][j], y, 0x3f3f3f3f);
            if (j > 1) addedge(x, id[i][j - 1], 0x3f3f3f3f), addedge(id[i][j - 1], y, 0x3f3f3f3f);
            if (i < n) addedge(x, id[i + 1][j], 0x3f3f3f3f), addedge(id[i + 1][j], y, 0x3f3f3f3f);
            if (j < m) addedge(x, id[i][j + 1], 0x3f3f3f3f), addedge(id[i][j + 1], y, 0x3f3f3f3f);
        }
    }
    int maxflow = 0, flow = 0;
    while (bfs()) while (flow = dinic(st, 0x3f3f3f3f)) maxflow += flow;
    cout << sum - maxflow << endl;
    return 0;
} 
View Code

芯片难题 Chips Challenge

 

无源汇有上下界可行流

#include <bits/stdc++.h>

using namespace std;


inline int read() {
    int out = 0; bool flag = false;
    register char cc = getchar();
    while (cc < '0' || cc > '9') {
        if (cc == '-') flag = true;
        cc = getchar();
    }
    while (cc >= '0' && cc <= '9') {
        out = (out << 3) + (out << 1) + (cc ^ 48);
        cc = getchar();
    } 
    return flag ? -out : out;
}

inline void write(int x, char ch) {
    if (x < 0) putchar('-'), x = -x;
    if (x == 0) putchar('0');
    else {
        int num = 0; char cc[22];
        while (x) cc[++num] = x % 10 + 48, x /= 10;
        while (num) putchar(cc[num--]);
    }
    putchar(ch);
}

const int N = 210, M = 42000;

int n, m, s, t, inf[N], outf[N], dow[M];

int head[N], to[M], nxt[M], edge[M], cnt = 1, h[N];

void add_edge(int u, int v, int w) {
    to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt;
}

void addedge(int u, int v, int w) {
    add_edge(u, v, w), add_edge(v, u, 0);
}

queue<int> q; int d[N];

bool bfs() {
    while (q.size()) q.pop();
    for (int i = 0; i <= t; i++) d[i] = 0, h[i] = head[i];
    q.push(s), d[s] = 1;
    while (q.size()) {
        int u = q.front(); q.pop();
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (edge[i] && !d[v]) {
                d[v] = d[u] + 1;
                if (v == t) return true;
                q.push(v);
            }
        }
    }
    return false;
}

int dinic(int u, int flow) {
    if (u == t) return flow;
    int rest = flow, now;
    for (int &i = h[u]; i; i = nxt[i]) {
        int v = to[i];
        if (edge[i] && d[v] == d[u] + 1) {
            now = dinic(v, min(rest, edge[i]));
            edge[i] -= now, edge[i ^ 1] += now, rest -= now;
        }
    }
    return flow - rest;
}

int main() {
    n = read(), m = read();
    s = 0, t = n + 1;
    for (int i = 1; i <= m; i++) {
        int u = read(), v = read(), down = read(), up = read(); 
        outf[u] += down, inf[v] += down, dow[i] = down, addedge(u, v, up - down);
    }
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        if (inf[i] > outf[i]) addedge(s, i, inf[i] - outf[i]);
        if (inf[i] < outf[i]) addedge(i, t, outf[i] - inf[i]);
    }
    while (bfs()) dinic(s, 0x3f3f3f3f);
    bool flag = false;
    for (int i = head[s]; i; i = nxt[i]) if (!(i & 1)) flag |= (edge[i] != 0);
    if (flag) puts("NO");
    else {
        puts("YES");
        for (int i = 2; i <= (m << 1); i += 2) write(dow[i >> 1] + edge[i ^ 1], '
');
    }
    return 0;
} 
View Code

 

[AHOI2014/JSOI2014]支线剧情

#include <bits/stdc++.h>

using namespace std;

const int N = 310, M = 12000;

int n, k, f[310], s, t, S, T, ans;

int head[N], to[M], nxt[M], edge[M], cst[M], cnt = 1, h[N];

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

void addedge(int u, int v, int w, int c) {
    add_edge(u, v, w, c), add_edge(v, u, 0, -c);
}

queue<int> q; int dis[N]; bool vis[N];

bool spfa() {
    for (int i = 0; i <= T; i++) dis[i] = 0x3f3f3f3f, vis[i] = false, h[i] = head[i];
    q.push(S), dis[S] = 0;
    while (q.size()) {
        int u = q.front(); q.pop();
        vis[u] = false;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (edge[i] && dis[v] > dis[u] + cst[i]) {
                dis[v] = dis[u] + cst[i];
                if (!vis[v]) vis[v] = true, q.push(v);
            }
        }
    }
    return dis[T] != 0x3f3f3f3f;
} 

int dinic(int u, int flow) {
    if (u == T) return flow;
    int rest = flow, now;
    vis[u] = true;
    for (int &i = h[u]; i; i = nxt[i]) {
        int v = to[i];
        if (!vis[v] && edge[i] && dis[v] == dis[u] + cst[i]) {
            now = dinic(v, min(rest, edge[i]));
            edge[i] -= now, edge[i ^ 1] += now, rest -= now;
            ans += now * cst[i];
        }
    }
    vis[u] = false;
    return flow - rest;
}

int main() {
    scanf("%d", &n);
    s = 1, t = n + 1, S = 0, T = n + 2;
    for (int u = 1; u <= n; u++) {
        scanf("%d", &k);
        for (int j = 1; j <= k; j++) {
            int v, c; scanf("%d%d", &v, &c);
            f[u]--, f[v]++, addedge(u, v, 0x3f3f3f3f, c), ans += c;
        }
        addedge(u, t, 0x3f3f3f3f, 0);
    }
    for (int i = 1; i <= n; i++) {
        if (f[i] > 0) addedge(S, i, f[i], 0);
        if (f[i] < 0) addedge(i, T, -f[i], 0);
    }
    addedge(t, s, 0x3f3f3f3f, 0);
    while (spfa()) dinic(S, 0x3f3f3f3f);
    cout << ans << endl;
    return 0;
}
View Code

[NEERC2016]Mole Tunnels

#include <bits/stdc++.h>

using namespace std;

int n, m, c[100010], u, pos[100010], dis[100010], fa[100010], ls[100010], rs[100010], ans;

void dfs(int u) {
    if (u > n) return ;
    dfs(u << 1), dfs(u << 1 | 1);
    if (c[u]) dis[u] = 0, pos[u] = u;
    else dis[u] = 0x3f3f3f3f, pos[u] = -1;
    if ((u << 1) <= n && dis[u] > dis[u << 1] + 1) dis[u] = dis[u << 1] + 1, pos[u] = pos[u << 1];
    if ((u << 1 | 1) <= n && dis[u] > dis[u << 1 | 1] + 1) dis[u] = dis[u << 1 | 1] + 1, pos[u] = pos[u << 1 | 1];
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
    dfs(1);
    for (int i = 1; i <= m; i++) {
        scanf("%d", &u);
        int now = u, s = 0, res = 0x3f3f3f3f, v = -1;
        while (now) {
            if (res > s + dis[now]) res = s + dis[now], v = now;
            if (fa[now] > 0) s -= 1;
            else s += 1;
            now >>= 1;
        }
        printf("%d ", ans += res);
        now = v, v = pos[v];
        c[v]--;
        while (v != now) {
            int ff = v >> 1;
            if (v == (ff << 1)) {
                if (ls[ff] > 0) ls[ff]--;
                else fa[v]++;
            }  
            else {
                if (rs[ff] > 0) rs[ff]--;
                else fa[v]++;
            }
            if (c[v]) dis[v] = 0, pos[v] = v;
            else dis[v] = 0x3f3f3f3f, pos[v] = -1;
            if ((v << 1) <= n && dis[v] > dis[v << 1] + (ls[v] ? -1 : 1)) dis[v] = dis[v << 1] + (ls[v] ? -1 : 1), pos[v] = pos[v << 1];
            if ((v << 1 | 1) <= n && dis[v] > dis[v << 1 | 1] + (rs[v] ? -1 : 1)) dis[v] = dis[v << 1 | 1] + (rs[v] ? -1 : 1), pos[v] = pos[v << 1 | 1];
            v = ff;
        }
        while (u != now) {
            if (fa[u]) fa[u]--;
            else {
                if (((u >> 1) << 1) == u) ls[u >> 1]++;
                else rs[u >> 1]++;
            }
            if (c[u]) dis[u] = 0, pos[u] = u;
            else dis[u] = 0x3f3f3f3f, pos[u] = -1;
            if ((u << 1) <= n && dis[u] > dis[u << 1] + (ls[u] ? -1 : 1)) dis[u] = dis[u << 1] + (ls[u] ? -1 : 1), pos[u] = pos[u << 1];
            if ((u << 1 | 1) <= n && dis[u] > dis[u << 1 | 1] + (rs[u] ? -1 : 1)) dis[u] = dis[u << 1 | 1] + (rs[u] ? -1 : 1), pos[u] = pos[u << 1 | 1];
            u >>= 1;
        }
        while (now) {
            if (c[now]) dis[now] = 0, pos[now] = now;
            else dis[now] = 0x3f3f3f3f, pos[now] = -1;
            if ((now << 1) <= n && dis[now] > dis[now << 1] + (ls[now] ? -1 : 1)) dis[now] = dis[now << 1] + (ls[now] ? -1 : 1), pos[now] = pos[now << 1];
            if ((now << 1 | 1) <= n && dis[now] > dis[now << 1 | 1] + (rs[now] ? -1 : 1)) dis[now] = dis[now << 1 | 1] + (rs[now] ? -1 : 1), pos[now] = pos[now << 1 | 1];
            now >>= 1;
        }
    }
    return 0;
} 
View Code

 

原文地址:https://www.cnblogs.com/Urushibara-Ruka/p/14515477.html