ACM-ICPC 2018 沈阳赛区网络预赛 Fantastic Graph 可行流

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Swingss/article/details/82627719

题目链接:https://nanti.jisuanke.com/t/31447

这题是个可行流,网上搜了一堆题解发现都是贪心,然而我对拍了一下发现都有过不了的数据,我猜八成这题是不能用贪心解的,只能说题目数据太弱了。

加一个源点和一个汇点。建图。源点到左边点的容量为 [L, min(R, cnt[i])],(cnt[i] 为原图中点 i 的度数,[x, y] 表示该边流量的下界为 x,上界为 y);左边点到右边点容量为 [0, 1];右边点到汇点的容量为 [L, min(R, cnt[i])],含义与前面相同。然后跑一遍可行流就好了。

AC代码如下:

#include <algorithm>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <vector>

using namespace std;

const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
// const double PI = acos(-1.0);
// const int MOD = 1000000007;

typedef long long LL;
typedef unsigned long long uLL;
const int N = 2000 * 2 + 10;
const int M = 2000000 + 10;

int n, m, k;
int L, R;
struct edge {
    int a, b, cap;
};
vector<edge> es;
vector<int> g[N];
int s, t;
int x, y;

inline void addedge(int a, int b, int cap) {
    if (cap == 0) return;
    es.push_back({a, b, cap});
    es.push_back({b, a, 0});
    int i = es.size();
    g[a].push_back(i - 2);
    g[b].push_back(i - 1);
}

int d[N];
bool bfs() {
    memset(d, -1, sizeof(d));
    queue<int> q;
    q.push(x);
    d[x] = 0;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (auto i : g[u]) {
            int v = es[i].b;
            if (d[v] < 0 && es[i].cap > 0) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d[y] >= 0;
}

bool vis[N];
int dfs(int u, int f) {
    if (u == y) return f;
    int ans = 0;
    vis[u] = true;
    for (auto i : g[u]) {
        int v = es[i].b;
        if (!vis[v] && d[v] == d[u] + 1 && es[i].cap > 0) {
            int flow = dfs(v, min(f, es[i].cap));
            if (flow > 0) {
                es[i].cap -= flow;
                es[i ^ 1].cap += flow;
                ans += flow;
                f -= flow;
                if (f <= 0) break;
            }
        }
    }
    return ans;
}

int dinic() {
    int ans = 0;
    while (bfs()) {
        int flow;
        while (memset(vis, 0, sizeof(vis)), flow = dfs(x, INF)) ans += flow;
    }
    return ans;
}

bool solve() {
    dinic();
    bool ok = true;
    for (auto i : g[x]) {
        if (es[i].cap != 0) ok = false;
    }
    for (auto i : g[y]) {
        if (es[i].cap != L) ok = false;
    }
    return ok;
}

int cnt[N];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int cs = 0;
    while (cin >> n >> m >> k) {
        cout << "Case " << ++cs << ": ";
        cin >> L >> R;
        t = n + m + 1;
        x = t + 1;
        y = t + 2;
        for (int i = 0; i <= y; ++i) g[i].clear();
        es.clear();
        memset(cnt, 0, sizeof(cnt));
        for (int i = 0; i < k; ++i) {
            int u, v;
            cin >> u >> v;
            ++cnt[u];
            ++cnt[v + n];
            addedge(u, v + n, 1);
            addedge(u, y, 0);
            addedge(x, v, 0);
        }
        for (int i = 1; i <= n; ++i) {
            if (cnt[i] < L) goto NO;
            addedge(s, i, min(cnt[i], R) - L);
            addedge(s, y, L);
            addedge(x, i, L);
        }
        for (int i = n + 1; i < t; ++i) {
            if (cnt[i] < L) goto NO;
            addedge(i, t, min(cnt[i], R) - L);
            addedge(i, y, L);
            addedge(x, t, L);
        }
        addedge(t, s, INF);
        if (solve()) {
            cout << "Yes\n";
            continue;
        }
    NO:
        cout << "No\n";
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Swingss/article/details/82627719