洛谷 P3128 [USACO15DEC]最大流Max Flow(LCA+树上差分)

Description:

Farmer John has installed a new system of N 1 N-1 N1 pipes to transport milk between the N N N stalls in his barn ( 2 N 50 , 000 2 \leq N \leq 50,000 2N50,000), conveniently numbered 1 N 1 \ldots N 1N. Each pipe connects a pair of stalls, and all stalls are connected to each-other via paths of pipes.

FJ is pumping milk between K K K pairs of stalls ( 1 K 100 , 000 1 \leq K \leq 100,000 1K100,000). For the i i ith such pair, you are told two stalls s i s_i si and t i t_i ti, endpoints of a path along which milk is being pumped at a unit rate. FJ is concerned that some stalls might end up overwhelmed with all the milk being pumped through them, since a stall can serve as a waypoint along many of the K K K paths along which milk is being pumped. Please help him determine the maximum amount of milk being pumped through any stall. If milk is being pumped along a path from s i s_i si to t i t_i ti, then it counts as being pumped through the endpoint stalls s i s_i si and t i t_i ti, as well as through every stall along the path between them.

FJ给他的牛棚的N(2≤N≤50,000)个隔间之间安装了N-1根管道,隔间编号从1到N。所有隔间都被管道连通了。

FJ有K(1≤K≤100,000)条运输牛奶的路线,第i条路线从隔间si运输到隔间ti。一条运输路线会给它的两个端点处的隔间以及中间途径的所有隔间带来一个单位的运输压力,你需要计算压力最大的隔间的压力是多少。

Input:

The first line of the input contains N N N and K K K.

The next N 1 N-1 N1 lines each contain two integers x x x and y y y ( x y x \ne y x̸=y) describing a pipe between stalls x x x and y y y.

The next K K K lines each contain two integers s s s and t t t describing the endpoint stalls of a path through which milk is being pumped.

Output:

An integer specifying the maximum amount of milk pumped through any stall in the barn.

Sample Input:

5 10
3 4
1 5
4 2
5 4
5 4
5 4
3 5
4 3
4 3
1 3
3 5
5 4
1 5
3 4

Sample Output:

9

题目链接

求被经过次数最多的点。

思路很显然LCA+树上差分。

AC代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 5e4 + 5;

struct Edge {
    int V, Next;
};

Edge edges[maxn << 1];
int Head[maxn];
int Tot;

void Init() {
    Tot = 0;
    memset(Head, -1, sizeof(Head));
}

void AddEdge(int U, int V) {
    edges[Tot] = Edge {V, Head[U]};
    Head[U] = Tot++;
}

int Rmq[maxn << 1];

struct ST {
    int Dp[maxn << 1][20];
    void Init(int N) {
        for (int i = 1; i <= N; ++i) {
            Dp[i][0] = i;
        }
        for (int j = 1; (1 << j) <= N; ++j) {
            for (int i = 1; i + (1 << j) - 1 <= N; ++i) {
                Dp[i][j] = Rmq[Dp[i][j - 1]] < Rmq[Dp[i + (1 << (j - 1))][j - 1]] ? Dp[i][j - 1] : Dp[i + (1 << (j - 1))][j - 1];
            }
        }
    }
    int Query(int A, int B) {
        if (A > B) {
            swap(A, B);
        }
        int Len = int(log2(B - A + 1));
        return Rmq[Dp[A][Len]] <= Rmq[Dp[B - (1 << Len) + 1][Len]] ? Dp[A][Len] : Dp[B - (1 << Len) + 1][Len];
    }
};

int Vertex[maxn << 1];
int First[maxn];
int Parent[maxn];
int LCATot;
ST St;

void LCADfs(int Cur, int Pre, int Depth) {
    Vertex[++LCATot] = Cur;
    First[Cur] = LCATot;
    Rmq[LCATot] = Depth;
    Parent[Cur] = Pre;
    for (int i = Head[Cur]; ~i; i = edges[i].Next) {
        if (edges[i].V == Pre) {
            continue;
        }
        LCADfs(edges[i].V, Cur, Depth + 1);
        Vertex[++LCATot] = Cur;
        Rmq[LCATot] = Depth;
    }
}

void LCAInit(int Root, int NodeNum) {
    LCATot = 0;
    LCADfs(Root, 0, 0);
    St.Init(2 * NodeNum - 1);
}

int QueryLCA(int U, int V) {
    return Vertex[St.Query(First[U], First[V])];
}

int N, K;
int Ans;
int Cnt[maxn];

int Dfs(int Cur, int Pre) {
    for (int i = Head[Cur]; ~i; i = edges[i].Next) {
        if (edges[i].V == Pre) {
            continue;
        }
        Cnt[Cur] += Dfs(edges[i].V, Cur);
    }
    Ans = max(Ans, Cnt[Cur]);
    return Cnt[Cur];
}

int main(int argc, char *argv[]) {
    Init();
    scanf("%d%d", &N, &K);
    for (int i = 1, X, Y; i < N; ++i) {
        scanf("%d%d", &X, &Y);
        AddEdge(X, Y);
        AddEdge(Y, X);
    }
    memset(Parent, 0, sizeof(Parent));
    LCAInit(1, N);
    memset(Cnt, 0, sizeof(Cnt));
    for (int i = 1, S, T; i <= K; ++i) {
        scanf("%d%d", &S, &T);
        int LCA = QueryLCA(S, T);
        Cnt[S]++; Cnt[T]++;
        Cnt[LCA]--; Cnt[Parent[LCA]]--;
    }
    Ans = 0;
    Dfs(1, 0);
    printf("%d\n", Ans);
    return 0;
}
全部评论

相关推荐

最近和朋友聊天,她说了句让我震惊的话:"我发现我连周末点外卖都开始'最优解'了,一定要赶在高峰期前下单,不然就觉得自己亏了。"这不就是典型的"班味入侵"吗?工作思维已经渗透到生活的方方面面。
小型域名服务器:啊?我一直都这样啊?我还以为是我爱贪小便宜呢?每次去实验室都得接一杯免费的开水回去,出门都得规划一下最短路径,在宿舍就吃南边的食堂,在实验室就吃北边的食堂,快递只有顺路的时候才取。
点赞 评论 收藏
分享
10-28 15:45
门头沟学院 C++
西南山:海康威视之前不是大规模裁员吗
点赞 评论 收藏
分享
喜欢走神的孤勇者练习时长两年半:爱华,信华,等华,黑华
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务