zoukankan      html  css  js  c++  java
  • P2402 奶牛隐藏 二分+网络流

    floyd搞出两点间最短距离 二分判答案

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1050;
    const int MAXM = 50050;
    const ll INF = 1LL << 50;
    ll f[MAXM << 1];
    int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], ed = 1, S, T;
    inline void read(ll &v)
    {
        v = 0;
        char c = 0;
        ll p = 1;
        while (c < '0' || c > '9') {
            if (c == '-') {
                p = -1;
            }
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            v = (v << 3) + (v << 1) + c - '0';
            c = getchar();
        }
        v *= p;
    }
    inline void addedge(int u, int v, ll cap)
    {
        to[++ed] = v;
        nxt[ed] = Head[u];
        Head[u] = ed;
        f[ed] = cap;
        to[++ed] = u;
        nxt[ed] = Head[v];
        Head[v] = ed;
        f[ed] = 0;
        return;
    }
    inline bool BFS()
    {
        int u;
        memset(lev, -1, sizeof(lev));
        queue<int>q;
        lev[S] = 0;
        q.push(S);
        while (q.size()) {
            u = q.front();
            q.pop();
            for (int i = Head[u]; i; i = nxt[i])
                if (f[i] && lev[to[i]] == -1) {
                    lev[to[i]] = lev[u] + 1;
                    q.push(to[i]);
                    /*
                    if (to[i] == T)
                    {
                            return 1;
                    }
                    magic one way optimize
                    */
                }
        }
        memcpy(cur, Head, sizeof Head);
        return lev[T] != -1;
    }
    inline ll DFS(int u, ll maxf)
    {
        if (u == T || !maxf) {
            return maxf;
        }
        ll cnt = 0, tem;
        for (int &i = cur[u]; i; i = nxt[i])
            if (f[i] && lev[to[i]] == lev[u] + 1) {
                tem = DFS(to[i], min(maxf, f[i]));
                maxf -= tem;
                f[i] -= tem;
                f[i ^ 1] += tem;
                cnt += tem;
                if (!maxf) {
                    break;
                }
            }
        if (!cnt) {
            lev[u] = -1;
        }
        return cnt;
    }
    ll Dinic()
    {
        ll ans = 0;
        while (BFS()) {
            ans += DFS(S, 1LL << 50);
        }
        return ans;
    }
    void init(int SS, int TT)
    {
        memset(Head, 0, sizeof(Head));
        ed = 1;
        S = SS;
        T = TT;
        return;
    }
    ll n, m;
    ll u, v , c;
    ll s[MAXN], p[MAXN];
    ll dis[MAXN][MAXN];
    ll sum = 0;
    bool check(ll x)
    {
        memset(Head, 0, sizeof(Head));
        ed = 1;
        S = 0, T = 2 * n + 1;
        for (int i = 1; i <= n; i++) {
            addedge(S, i, s[i]);
            addedge(i + n, T, p[i]);
        }
        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                if (i == j) {
                    addedge(i, i + n, INF);
                } else if (dis[i][j] <= x) {
                    addedge(i, j + n, INF), addedge(j, i + n, INF);
                }
            }
        }
        if (Dinic() == sum) {
            return true;
        }
        return false;
    }
    int main()
    {
        ll x;
        read(n), read(m);
        for (int i = 1; i <= n; i++) {
            read(x), s[i] = x;
            read(x), p[i] = x;
            sum += s[i];
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i == j) {
                    dis[i][j] = 0;
                } else {
                    dis[i][j] = 1LL << 50;
                }
            }
        }
        for (int i = 1; i <= m; i++) {
            read(u), read(v), read(c);
            dis[u][v] = dis[v][u] = min(dis[u][v], c);
        }
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    if (dis[i][j] > dis[i][k] + dis[k][j]) {
                        dis[i][j] = dis[i][k] + dis[k][j];
                    }
                }
            }
        ll l = INF, r = -INF, mid;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i != j) {
                    if (dis[i][j] >= INF) {
                        continue;
                    }
                    r = max(dis[i][j], r);
                    l = min(l, dis[i][j]);
                }
            }
        }
        r++, l--;
        bool flag = false;
        while (l < r - 1) {
            mid = (l + r) >> 1;
            if (check(mid)) {
                r = mid;
                flag = true;
            } else {
                l = mid;
            }
        }
        if (flag) {
            cout << r << endl;
        } else {
            cout << -1 << endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C++ 数字、string 简便互转
    【C语言】递归函数DigitSum(n)
    UVALIVE 4287 Proving Equivalences (强连通分量+缩点)
    【linux驱动分析】misc设备驱动
    C++ auto 与 register、static keyword 浅析
    spring 计时器
    Spring注解配置定时任务<task:annotation-driven/>
    去除ckeditor上传图片预览中的英文字母
    编码规范
    git 手动操作
  • 原文地址:https://www.cnblogs.com/Aragaki/p/10698971.html
Copyright © 2011-2022 走看看