Mincut minimum percentage (BZOJ1797 + minimum percentage + tarjan)

Topic Link

Portal

Thinking

The title given maximum flow running side edge, and then run on the remaining network \ (Tarjan \) .

For each side are:

  • If it is non-full side, then it must not minimum cut set inside edge;
  • If \ (C [U [I]] \ = Not C [V [I]] \) , then it may be the minimum cut set inside edge;
  • If \ (c [u [i] ] \ not = c [v [i]] \) and \ (c [u [i] ] = c [s], c [v [i] = c [t]] \) , then it must be the smallest cut set inside edge.

Details can be seen \ (hzwer \) to explain big brother.

Code to achieve the following

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 4000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int n, m, top, num, cnt, u, v, w;
int dfn[maxn], low[maxn], stc[maxn], vis[maxn], c[maxn];

struct Dinic {
    queue<int> q;
    int maxflow, tot, s, t;
    int head[maxn], d[maxn];
    void init() {
        tot = maxflow = 0;
        memset(head, -1, sizeof(head));
    }
    struct edge {
        int u, v, w, next;
    }ed[220007];
    void add(int u, int v, int w) {
        ed[tot].u = u;
        ed[tot].v = v;
        ed[tot].w = w;
        ed[tot].next = head[u];
        head[u] = tot++;
        ed[tot].u = v;
        ed[tot].v = u;
        ed[tot].w = 0;
        ed[tot].next = head[v];
        head[v] = tot++;
    }
    bool bfs() {
        memset(d, 0, sizeof(d));
        d[s] = 1;
        while(!q.empty()) q.pop();
        q.push(s);
        int x;
        while(!q.empty()) {
            x = q.front();
            q.pop();
            for(int i = head[x]; ~i; i = ed[i].next) {
                if(ed[i].w && !d[ed[i].v]) {
                    d[ed[i].v] = d[x] + 1;
                    q.push(ed[i].v);
                    if(ed[i].v == t) return 1;
                }
            }
        }
        return 0;
    }
    int dinic(int x, int flow) {
        if(x == t) return flow;
        int res = flow, k, v;
        for(int i = head[x]; ~i && res; i = ed[i].next) {
            v = ed[i].v;
            if(ed[i].w && d[v] == d[x] + 1) {
                k = dinic(v, min(res, ed[i].w));
                if(!k) d[v] = 0;
                ed[i].w -= k;
                ed[i^1].w += k;
                res -= k;
            }
        }
        return flow - res;
    }
    int work() {
        int flow = 0;
        while(bfs()) {
            while(flow = dinic(s, inf)) maxflow += flow;
        }
        return maxflow;
    }
}f;

void tarjan(int u) {
    dfn[u] = low[u] = ++num;
    vis[u] = 1, stc[++top] = u;
    int v;
    for(int i = f.head[u]; ~i; i = f.ed[i].next) {
        if(f.ed[i].w == 0) continue;
        v = f.ed[i].v;
        if(!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if(vis[v]) {
            low[u] = min(low[u], low[v]);
        }
    }
    if(dfn[u] == low[u]) {
        cnt++;
        do {
            v = stc[top--];
            vis[v] = 0;
            c[v] = cnt;
        }while(u != v);
    }
}

int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif
    scanf("%d%d%d%d", &n, &m, &f.s, &f.t);
    f.init();
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &u, &v, &w);
        f.add(u, v, w);
    }
    f.work();
    for(int i = 1; i <= n; ++i) {
        if(!dfn[i]) tarjan(i);
    }
    for(int i = 0; i < f.tot; i += 2) {
        if(f.ed[i].w) {
            printf("0 0\n");
            continue;
        }
        int u = f.ed[i].u, v = f.ed[i].v;
        if(c[u] != c[v]) printf("1 ");
        else printf("0 ");
        if(c[u] == c[f.s] && c[v] == c[f.t]) printf("1\n");
        else printf("0\n");
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Dillonh/p/11236173.html