[ACWing]2277. Secret milking machine

Posted by scottd on Fri, 11 Feb 2022 06:58:08 +0100

Title address:

https://www.acwing.com/problem/content/2279/

Farmer John is making a new milking machine and hopes to keep it strictly confidential. He hid the milking machine deep in the farm, enabling him to carry out the task without being found. In the process of machine manufacturing, he has to carry out a total between the cowshed and the milking machine T T T round trips. He has a secret passage that can only be used on his return trip. Farm by N N N landmarks (No.) 1 ∼ N 1∼N 1 ∼ N), these landmarks are composed of P P P two-way roads (No 1 ∼ P 1∼P 1 ∼ P) connection. The length of each road is positive and does not exceed 1 0 6 10^6 106. Multiple roads may connect the same pair of landmarks. In order to minimize the possibility of being found, any road in the farm can only be used once at most, and he should try to use the shortest road as possible. Help John from the cowshed (landmark) 1 1 1) Arrive at the secret milking machine (landmark) N N N) Altogether T T T times. Find the minimum possible length of the longest single road he must use. Note that the goal is to minimize the length of the longest road used, not the sum of the lengths of all roads used. Make sure John can finish without repeating the path T T T trips.

Input format:
The first line contains three integers N , P , T N,P,T N,P,T. next P P P line, each line contains three integers A i , B i , L i A_i,B_i,L_i Ai, Bi and Li represent landmarks A i A_i Ai and B i B_i Between Bi , there is a line with a length of L i L_i Li's road.

Output format:
Outputs an integer representing the minimum possible length of the longest single road John must use.

Data range:
1 ≤ T ≤ 200 1≤T≤200 1≤T≤200
2 ≤ N ≤ 200 2≤N≤200 2≤N≤200
1 ≤ P ≤ 40000 1≤P≤40000 1≤P≤40000
1 ≤ A i , B i ≤ N 1≤A_i,B_i≤N 1≤Ai​,Bi​≤N
1 ≤ L i ≤ 1 0 6 1≤L_i≤10^6 1≤Li​≤106

This question is equivalent to asking, from the beginning to the end, go through the disjoint path T T T paths, if you want to make the longest side of all paths the shortest, how short can it be. This can be done in two, enumerating a lower bound of length x x x. Then delete all edges longer than x x The side of x, see if you can find it T T T disjoint paths. If they can be found, the answer can at least be x x x (also possible than x x x (small), if not found, the answer must be greater than x x x (i.e. add back some edges). And judge whether it exists T T T disjoint paths can be considered by network flow. Build the network first. The vertex is the same as the graph in the edge topic, but the edge weight is set to 1 1 1, and both sides are bidirectional. Considering the correspondence, for T T T disjoint paths flow directly on each edge of all paths 1 1 1, which is obviously an integer feasible flow; For an integer feasible flow (each side flows integers), if an edge flows twice (the edge in this question is a two-way edge, which means both forward and reverse flow), then clear the flow of both sides as 0 0 0, the result is still an integer feasible flow, and the specific T T T paths can be searched directly from the starting point T T T times. Judge the existence of T T T paths only need to see whether the maximum flow is greater than or equal to T T T, Dinic algorithm can be used. The code is as follows:

#include <iostream>
#include <cstring>
using namespace std;

const int N = 210, M = 80010, INF = 1e8;
int n, m, K, S, T;
int h[N], e[M], f[M], w[M], ne[M], idx;
int q[N], d[N], cur[N];

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    e[idx] = a, w[idx] = c, ne[idx] = h[b], h[b] = idx++;
}

bool bfs() {
    int hh = 0, tt = 0;
    memset(d, -1, sizeof d);
    q[tt++] = S, d[S] = 0, cur[S] = h[S];
    while (hh < tt) {
        int t = q[hh++];
        for (int i = h[t]; ~i; i = ne[i]) {
            int v = e[i];
            if (d[v] == -1 && f[i]) {
                d[v] = d[t] + 1;
                if (v == T) return true;

                cur[v] = h[v];
                q[tt++] = v;
            }
        }
    }

    return false;
}

int dfs(int u, int limit) {
    if (u == T) return limit;
    int flow = 0;
    for (int i = cur[u]; ~i && flow < limit; i = ne[i]) {
        cur[u] = i;
        int v = e[i];
        if (d[v] == d[u] + 1 && f[i]) {
            int t = dfs(v, min(limit - flow, f[i]));
            if (!t) d[v] = -1;
            f[i] -= t, f[i ^ 1] += t, flow += t;
        }
    }

    return flow;
}

int dinic() {
    int r = 0, flow;
    while (bfs()) while (flow = dfs(S, INF)) r += flow;
    return r;
}

bool check(int mid) {
	// The edge has been built. You need to assign the flow
    for (int i = 0; i < idx; i++) 
        if (w[i] > mid) f[i] = 0;
        else f[i] = 1;
        
    // Judge whether there is a flow with a flow greater than or equal to K. if there is, K disjoint paths can be taken
    return dinic() >= K;
}

int main() {
    scanf("%d%d%d", &n, &m, &K);
    S = 1, T = n;
    memset(h, -1, sizeof h);
    int r = 0;
    // Build the map first, but do not build the capacity of the edge. The capacity of the edge will be determined when it is halved
    while (m--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
        // The right end of the search range is the one with the largest edge weight of all edges
        r = max(r, c);
    }

    int l = 1;
    while (l < r) {
        int mid = l + (r - l >> 1);
        if (check(mid)) r = mid;
        else l = mid + 1;
    }

    printf("%d", l);

    return 0;
}

Time complexity O ( n 2 m log ⁡ r ) O(n^2m\log r) O(n2mlogr), r r r is the search scope, space O ( n ) O(n) O(n).

Topics: network Algorithm Graph Theory