羅区P3128 LCA +木の違い

トピックリンク:ポイントI

件名の説明:

FJ彼の納屋にNが導管のN-1(2≤N≤50,000)コンパートメントの間に設置し、区画は1からNまで番号が付けられています すべてのコンパートメントは、通信パイプです。

そこFJ K(1≤K≤100,000)ミルク搬送経路、から通じる経路i番目の区画に区画SI TI。圧力輸送ルートがユニットの輸送に圧力をもたらすために、そのコンパートメントと2つの端点の中央ルートのすべてのコンパートメントを与える、あなたはコンパートメントがある最大圧力を計算する必要があります。

問題の意味

無根木であり、k番目の圧力、最大圧力点の後、どのくらいの圧力、(包括的)はSのTパスプラス圧ユニットに点まで続けます。

問題の解決策

LCA +ツリー差動
U-> V路内の圧力が、それに分解することができれば、ルートノード、圧力各ノードのDISアレイレコードを識別するために望むことができるU-> LCA、lca-> Vパス2とのそれぞれ圧力。
:差動動作範囲のために行うことができるため、
数字のセットがある場合:12345
11111:後に配列の違いをddは
2-4 3-5に1を加算してマイナス1
、必要にのみ微分アレイの動作を指示次いで、プレフィックスと再度回答を取得しようとする:
[1 4 +] DD [2] ++、DDを- 、++(無効果に相当する範囲にわたる)、DD - [3] DD; [+ 5 1。]
動作ポスト差動アレイDD:1つの2 0 1 0
プレフィックスと:最終回答の操作後13344。
また、このアイデアを使用し、ツリーの違いは、それが+に相当するツリーの各点のニーズがU-する差、>根、V-> U-のルート> V + 1点ずつ、となります図1は、uは、各点マイナス1のルートに共通の祖先をV。
圧力のニーズが最近の共通の祖先で個別に記録されるので、Uは、操作した後、最新の共通祖先の圧力vは、ゼロになります。
DIS [U] ++、DIS [ V] ++、DIS [LCA] - = 2;
最新別々に記録DIS1圧力共通の祖先を持つ:DIS1 [LCA] ++;
前回とプレフィックスツリーは、再度、DFSを検索し、なお、最大値もそれを記録しました。
max_ans = MAX(max_ans、DIS [ CUR] + DIS1 [CUR])。

ここに画像を挿入説明

#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;
}

変形タイトル:ポイント差 - >差動エッジ

そうでない場合は、各点のそれぞれを加圧するが、からのすべての側面のためのS->トンで加圧され、どのようにそれを見つけるには?実際には、このような変更が、それはまた単純であること、DISの意味を変更します:DIS [i]をエッジに私トラフィックの前にポイントを表します。このため、共通の祖先の非存在下のオフセット圧力値は、圧力共通の祖先の別個の記録0ではありません。差動、接頭辞、および答えを得るために。

公開された41元の記事 ウォンの賞賛2 ビュー1217

おすすめ

転載: blog.csdn.net/qq_41418281/article/details/104064693