Luo Gu P3128 LCA + trees difference

Topic links: point I

Subject description:

FJ to his barn N installed between N-1 of conduits (2≤N≤50,000) compartments, the compartments are numbered from 1 to N. All the compartments are in communication pipe.

There FJ K (1≤K≤100,000) milk transport route, a route leading from the i-th compartment to compartment si ti. Pressure a transport route will give its compartment and all the compartments of the middle route of two endpoints to bring pressure on the transportation of a unit, you need to calculate the maximum pressure compartment is.

The meaning of problems

In an unrooted trees, and continue to a point so that s t path (inclusive) plus a pressure unit, after the k-th pressure, the maximum pressure point, how much pressure.

answer

LCA + tree differential
may wish to identify a root node, a pressure dis array record for each node, if the pressure in the u-> v path, it can be decomposed into u-> lca, lca-> v paths each with two pressure.
Because the differential can be done for Operating range:
If there is a set of numbers: 12,345
array dd Difference after: 11,111
to 2-4 adds 1 to 3-5 minus one
need only direct the operation of the differential array, prefix and then again seek to get the answer:
dd [2] ++, dd [+. 1. 4] -; dd [. 3] -, dd [+. 5. 1] ++ (over a range corresponding to no effect);
operating post differential array dd: 1 2 0 1 0
prefix and: 13,344 after the operation for the final answer.
Also use this idea, the difference in the tree, it becomes a tree difference, where each point needs to u-> root, v-> root of u-> v + 1 point each, equivalent to + 1, and u, v common ancestor to the root of each point minus one.
U After the operation, the most recent common ancestor pressure v becomes zero, so the pressure needs to be recorded separately at the recent common ancestor.
dis [u] ++, dis [ v] ++, dis [lca] - = 2;
with the latest separately recorded dis1 pressure common ancestor: dis1 [lca] ++;
last time and the prefix tree, search again DFS, Incidentally, the maximum value also recorded it.
max_ans = max (max_ans, dis [ cur] + dis1 [cur]);

Here Insert Picture Description

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false)
#define ll long long
#define maxn 50005
#define maxq 100005

struct node
{
    int value, order;
};
struct edge
{
    int to, next;
};

edge ff[2 * maxn];
int head[2 * maxn], num_edge;
void add_edge(int from, int to)
{
    ff[++num_edge].next = head[from];
    ff[num_edge].to = to;
    head[from] = num_edge;
}

vector<node>qq[maxq];       //离线存储输入
bool vis[maxn];
int yy[maxn], ans[maxq];     //yy为并查集合并数组

int find(int x)
{
    return yy[x] == x ? x : yy[x] = find(yy[x]);
}


void dfs(int from, int to)
{
    vis[to] = true;
    for (int i = head[to]; i; i = ff[i].next)
        if (ff[i].to != from)
            dfs(to, ff[i].to);
    for (int i = 0; i<qq[to].size(); i++)
        if (vis[qq[to][i].value] && ans[qq[to][i].order] == 0)
            ans[qq[to][i].order] = find(qq[to][i].value);
    yy[to] = find(from);
}

vector<pair<int,int> >V;

int dis[maxn];//树上差分,记录前向点(边)的差分流量
int dis1[maxn];
int max_ans=0;
void dfs2(int fa,int cur)
{
    int sum=0;
    for(int i=head[cur]; i; i=ff[i].next)
    {
        int to=ff[i].to;
        if(fa!=to)
        {
            dfs2(cur,to);
            dis[cur]+=dis[to];
        }
    }
    max_ans=max(max_ans,dis[cur]+dis1[cur]);
}

int main()
{
    IOS;
    int n, m;
    cin>>n>>m;

    for (int i = 0; i<n - 1; i++)
    {
        int x, y;
        cin>>x>>y;
        add_edge(x, y);
        add_edge(y, x);
    }

    for (int i = 0; i<m; i++)
    {
        int x, y;
        cin>>x>>y;

        V.push_back(make_pair(x,y));
        qq[x].push_back((node)
        {
            y, i + 1
        });
        qq[y].push_back((node)
        {
            x, i + 1
        });
    }

    for (int i = 0; i <= n; i++)yy[i] = i;

    dfs(1, 1);

    for(int i=0; i<V.size(); i++)
    {
        int id=i+1;
        int x=V[i].first,y=V[i].second;
        int lca=ans[id];
        dis[x]++,dis[y]++,dis[lca]-=2;
        dis1[lca]++;
        //cout<<dis[x]<<","<<dis[y]<<","<<dis[lca]<<"\n";
    }

    /*for(int i=1; i<=n; i++)
        cout<<dis[i]<<" ";
    cout<<"\n";*/
    dfs2(1,1);

    cout<<max_ans;
    return 0;
}

Deformation Title: Point Differential -> differential edge

If not pressurize each for each point, but for all sides from s-> t in pressurized, how to find it? In fact, such a change, but doing it is also simpler, will change the meaning of dis: dis [i] represents the point before i traffic to the edge. Because of this common ancestor absence offset pressure value is 0, no separate recording of pressure common ancestor. Differential, prefixes, and to get the answer.

Published 41 original articles · won praise 2 · Views 1217

Guess you like

Origin blog.csdn.net/qq_41418281/article/details/104064693