• POJ Secret Milking Machine 【网络流+二分】


    题意:各一个地图,两点之间有若干条路,要在节点1和节点n之间行走t次(就是问1到n的路径数至少为t,每一条路径不能有重复),问所有路径里面最长的部分(这个题目特别强调,不是路径长度和,是路径中相邻两点的距离)最小是多少。


    网络流+二分。

    二分路径最长的一段,根据二分值构图。

    构图方法:

    如果两点路径长度小于x,则两点之间连接一条边,权值为1(如果已经连接了,权值加1)。

    最大流既是从1到n不重复的路径条数,判断是否大于规定的t条即可。


    注意一下这题是无向图,两个方向的初始流量相等(有向图只有一个方向有流量,另外一个方向的流量初始为0)。


    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define N 240
    #define INF 0x3f3f3f3f
    
    class Dinic {
    public:
        int n, s, t, l[N], c[N][N], e[N];
        int flow(int maxf = INF) {
            int left = maxf;
            while (build()) left -= push(s, left);
            return maxf - left;
        }
        int push(int x, int f) {
            if (x == t) return f;
            int &y = e[x], sum = f;
            for (; y<n; y++)
                if (c[x][y] > 0 && l[x]+1==l[y]) {
                    int cnt = push(y, min(sum, c[x][y]));
                    c[x][y] -= cnt;
                    c[y][x] += cnt;
                    sum -= cnt;
                    if (!sum) return f;
                }
            return f-sum;
        }
        bool build() {
            int m = 0;
            memset(l, -1, sizeof(l));
            l[e[m++]=s] = 0;
            for (int i=0; i<m; i++) for (int y=0; y<n; y++)
                if (c[e[i]][y] > 0 && l[y]<0) l[e[m++]=y] = l[e[i]] + 1;
            memset(e, 0, sizeof(e));
            return l[t] >= 0;
        }
    } net;
    int n, p, t, a[40004], b[40004], c[40004];
    bool ok(int x) {
        memset(net.c, 0, sizeof(net.c));
        net.s = 0, net.t = n-1, net.n = n;
    
        for (int i=0; i<p; i++) if (c[i] <= x)
            net.c[a[i]-1][b[i]-1]++, net.c[b[i]-1][a[i]-1]++; //本题是无向图,所以 i->j 和 j->i 都要增加
    
        return net.flow() >= t;
    }
    int main() {
    
        scanf("%d%d%d", &n, &p, &t);
    
        for (int i=0; i<p; i++) scanf("%d%d%d", &a[i], &b[i], &c[i]);
    
        int l = 0, r = INF, mid, ans;
    
        while (l <= r) {
            mid = (l + r) >> 1;
            if (ok(mid)) {
                ans = mid;
                r = mid - 1;
            } else l = mid + 1;
        }
        cout << ans << endl;
    
        return 0;
    }
    
    
    
    


  • 相关阅读:
    简单实用游标更改数据
    C# Http以文件的形式上传文件
    简单例子理解数据库事务
    安卓 隐藏按钮
    jQuery EasyUI API 中文文档
    Linux搭建Tomcat环境
    linux教程之一
    Android服务之PackageManagerService启动源码分析
    DSP、Media、AdExchanger之间的关系及交互流程
    Unity3D中的Coroutine具体解释
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3141094.html
Copyright © 2020-2023  润新知