• [CTSC2018]暴力写挂


    题面

    给出两颗树\(A,B\),求\(\max(A_{dis}(x,y) + dep_{A_{lca}\ }(x,y) + dep_{B_{\ lca}\ }\ (x,y))\)

    解法

    考虑改写柿子答案为\(\frac{1}{2}\max(A_{dis}(x,y) + dep_x + dep_y - 2 dep_{B_{\ lca}\ }(x,y))\)

    考虑淀粉质,把分治中点统领范围的点拉出来在\(B\)上建出虚树,关键点点权赋值为\(dis(mid,x) + dep(x)\),同一个子树赋值同一个颜色,在虚树上\(dp\)不同颜色的\(\max val(x) + val(y) - 2dep(lca)\)即可。

    点击查看代码
    //晦暗的宇宙,我们找不到光,看不见尽头,但我们永远都不会被黑色打倒。——Quinn葵因
    #include <bits/stdc++.h>
    #define ll long long
    #define N 1000000
    using std::vector;
    using std::pair;
    
    int n;
    
    #define pil pair<int,ll>
    #define mp std::make_pair
    
    vector<pil>A[N], B[N]; //tree
    
    ll depa[N], depb[N];
    int dep[N];
    
    inline void dfsa(int u, int fa) {
        //  std::cout<<u<<" "<<fa<<" "<<depa[u]<<"\n";
        for (auto it : A[u]) {
            int x = it.first;
            ll v = it.second;
    
            if (x == fa)
                continue;
    
            depa[x] = depa[u] + v;
            dfsa(x, u);
        }
    }
    
    int F[N][20];
    
    int dfn[N];
    int cnt;
    
    inline void dfsb(int u, int fa) {
        F[u][0] = fa;
        dep[u] = dep[fa] + 1;
    
        for (int i = 1; i <= 19; ++i)
            F[u][i] = F[F[u][i - 1]][i - 1];
    
        dfn[u] = ++cnt;
    
        for (auto it : B[u]) {
            int x = it.first;
            ll v = it.second;
    
            if (x == fa)
                continue;
    
            depb[x] = depb[u] + v;
            dfsb(x, u);
        }
    }
    
    int sum, siz[N], root;
    int maxn[N];
    
    ll val[N];
    int c[N];
    int vis[N];
    
    inline void find(int u, int fa) {
        siz[u] = 1;
        maxn[u] = 1;
    
        for (auto it : A[u]) {
            int v = it.first;
    
            if (v == fa || vis[v])
                continue;
    
            find(v, u);
            siz[u] += siz[v];
            maxn[u] = std::max(maxn[u], siz[v]);
        }
    
        maxn[u] = std::max(maxn[u], sum - siz[u]);
    
        //  std::cout<<"FIND "<<u<<" "<<maxn[u]<<"\n";
        if (maxn[u] < maxn[root])
            root = u;
    }
    
    vector<int>P;
    
    inline void dis(int u, int fa) {
        //  std::cout<<"DIS "<<u<<" "<<fa<<" "<<val[u]<<"\n";
        c[u] = c[fa];
    
        for (auto it : A[u]) {
            int v = it.first;
            ll vi = it.second;
    
            if (vis[v] || v == fa)
                continue;
    
            val[v] = val[u] + vi;
            dis(v, u);
        }
    
        val[u] = val[u] + depa[u];
        P.push_back(u);
    }
    
    inline int lca(int x, int y) {
        //  std::cout<<"LCA "<<x<<" "<<y<<"\n";
        if (dep[x] < dep[y])
            std::swap(x, y);
    
        for (int i = 19; i >= 0; --i) {
            if (dep[F[x][i]] >= dep[y])
                x = F[x][i];
    
            //      std::cout<<x<<"\n";
        }
    
        if (x == y)
            return x;
    
        for (int i = 19; i >= 0; --i) {
            if (F[x][i] != F[y][i])
                x = F[x][i], y = F[y][i];
    
            //      std::cout<<"UP "<<x<<" "<<y<<"\n";
        }
    
        return F[x][0];
    }
    
    inline bool cmp(int x, int y) {
        return dfn[x] < dfn[y];
    }
    
    ll f[N][2];
    
    bool key[N];
    
    int Fi[N];
    
    ll ans = -1e18;
    
    #define pii pair<ll,int>
    
    vector<pii>M;
    
    inline void merge(int x, int y) { //y -> x
        for (int i = 0; i < 2; ++i)
            for (int j = 0; j < 2; ++j)
                if (c[f[x][i]] != c[f[y][j]])
                    ans = std::max(ans, val[f[x][i]] + val[f[y][j]] - 2 * depb[x]);
    
        //    bool tag = 0;
        //
        //    if (val[f[y][0]] < val[f[y][1]])
        //        std::swap(f[y][0], f[y][1]);
        //
        //    if (val[f[x][0]] < val[f[x][1]])
        //        std::swap(f[x][0], f[x][1]);
        //
        //    if (val[f[y][0]] > val[f[x][0]]) {
        //        if (c[f[y][0]] != c[f[x][0]])
        //            f[x][1] = f[x][0];
        //
        //        f[x][0] = f[y][0];
        //        tag = 1;
        //    } else {
        //        if (val[f[y][0]] > val[f[x][1]] && c[f[y][0]] != c[f[x][0]]) {
        //            f[x][1] = f[y][0];
        //            tag = 1;
        //        }
        //    }
        //
        //    if (!tag) {
        //        if (val[f[y][1]] > val[f[x][0]]) {
        //            if (c[f[y][1]] != c[f[x][0]])
        //                f[x][1] = f[x][0];
        //
        //            f[x][0] = f[y][1];
        //        } else {
        //            if (val[f[y][1]] > val[f[x][1]] && c[f[y][1]] != c[f[x][0]]) {
        //                f[x][1] = f[y][1];
        //            }
        //        }
        //    }
    
        //  std::cout<<"CAO NI MA DE MERGE"<<"\n";
        //  std::cout<<x<<" "<<y<<"\n";
        //  std::cout<<f[x][0]<<" "<<c[f[x][0]]<<" "<<val[f[x][0]]<<"\n";
        //  std::cout<<f[x][1]<<" "<<c[f[x][1]]<<" "<<val[f[x][1]]<<"\n";
        //  std::cout<<f[y][0]<<" "<<c[f[y][0]]<<" "<<val[f[y][0]]<<"\n";
        //  std::cout<<f[y][1]<<" "<<c[f[y][1]]<<" "<<val[f[y][1]]<<"\n";
        M.clear();
        M.push_back(mp(-val[f[x][0]], f[x][0]));
        M.push_back(mp(-val[f[x][1]], f[x][1]));
        M.push_back(mp(-val[f[y][0]], f[y][0]));
        M.push_back(mp(-val[f[y][1]], f[y][1]));
        std::sort(M.begin(), M.end());
        //  puts("CAO NI MA DE WO sort GET");
        //  for(int i = 0;i <= 3;++i)
        //  std::cout<<-M[i].first<<" "<<M[i].second<<"\n";
        f[x][0] = M[0].second;
    
        for (int i = 1; i <= 3; ++i) {
            if (c[M[i].second] != c[f[x][0]]) {
                f[x][1] = M[i].second;
                //  std::cout<<f[x][0]<<" "<<c[f[x][0]]<<" "<<val[f[x][0]]<<"\n";
                //  std::cout<<f[x][1]<<" "<<c[f[x][1]]<<" "<<val[f[x][1]]<<"\n";
                return ;
            }
        }
    }
    
    inline int iread(){
       int s=0,w=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){ch=getchar();}
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    
    inline ll lread(){
       ll s=0,w=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    
    inline void build() {
        val[0] = -1e18;
        c[0] = -1;
        //  puts("FUCK BUILE THE WEAK TREE");
        std::sort(P.begin(), P.end(), cmp);
    
        for (int i = 0; i < P.size(); ++i)
            key[P[i]] = 1;/*,std::cout<<P[i]<<" ";
    
        puts("");   */
        int k = P.size();
    
        for (int i = 1; i < k; ++i)
            P.push_back(lca(P[i], P[i - 1]));
    
        //  std::cout<<"HELP "<<P[i]<<" "<<P[i - 1]<<" "<<lca(P[i],P[i - 1])<<"\n";
        std::sort(P.begin(), P.end(), cmp);
        P.erase(unique(P.begin(), P.end()), P.end());
    
        for (int i = 1; i < P.size(); ++i)
            Fi[P[i]] = lca(P[i], P[i - 1]);
    
        for (int i = 0; i < P.size(); ++i) {
            if (!key[P[i]])
                f[P[i]][0] = f[P[i]][1] = 0;
            else
                f[P[i]][0] = P[i], f[P[i]][1] = 0;
        }
    
        for (int i = P.size() - 1; i >= 1; --i) {
            int u = P[i];
            merge(Fi[u], u);
            //      std::cout<<"GLASS "<<u<<" "<<Fi[u]<<"\n";
            //      std::cout<<f[u][0]<<" "<<c[f[u][0]]<<" "<<val[f[u][0]]<<"\n";
            //      std::cout<<f[u][1]<<" "<<c[f[u][1]]<<" "<<val[f[u][1]]<<"\n";
            //        ans = std::max(ans, val[f[u][0]] + val[f[u][1]] - 2 * depb[u]);
            //      std::cout<<ans<<"\n";
        }
    
        //  std::cout<<"GLASS "<<P[1]<<" "<<Fi[P[1]]<<"\n";
        //  std::cout<<f[P[0]][0]<<" "<<c[f[P[0]][0]]<<" "<<val[f[P[0]][0]]<<"\n";
        //  std::cout<<f[P[0]][1]<<" "<<c[f[P[0]][1]]<<" "<<val[f[P[0]][1]]<<"\n";
        //    ans = std::max(ans, val[f[P[0]][0]] + val[f[P[0]][1]] - 2 * depb[P[0]]);
    
        for (int i = 0; i < P.size(); ++i)
            key[P[i]] = 0;
    }
    
    inline void solve(int u) {
        //    if (vis[u])
        //        return ;
    
        //  std::cout<<"DEL "<<u<<"\n";
        vis[u] = 1;
        find(u, 0);
        val[u] = depa[u];
        c[u] = u;
        P.clear();
        P.push_back(u);
    
        //  std::cout<<"FUCK DIS"<<"\n";
        for (auto it : A[u]) {
            int v = it.first;
            ll vi = it.second;
    
            if (vis[v])
                continue;
    
            val[v] = vi;
            c[v] = v;
            dis(v, v);
        }
    
        build();
    
        for (auto it : A[u]) {
            int v = it.first;
            sum = siz[v], root = 0;
    
            if (vis[v])
                continue;
    
            find(v, 0);
            //      std::cout<<u<<" FUCK "<<v<<" = "<<root<<"\n";
            solve(root);
        }
    }
    
    signed main() {
        //  freopen("q.in","r",stdin);
        //  freopen("q.out","w",stdout);
    //    scanf("%d", &n);
    	n = iread();
        for (int i = 1; i < n; ++i) {
            int x = iread(), y = iread();
            ll v = lread();
            A[x].push_back(mp(y, v));
            A[y].push_back(mp(x, v));
        }
    
        for (int i = 1; i < n; ++i) {
            int x = iread(), y = iread();
            ll v = lread();
            B[x].push_back(mp(y, v));
            B[y].push_back(mp(x, v));
        }
    
        dfsa(1, 0);
        dfsb(1, 0);
        maxn[0] = n * 2;
        root = 0;
        sum = n;
        find(1, 0);
        solve(root);
        ans = ans / 2;
    
        for (int i = 1; i <= n; ++i)
            ans = std::max(ans, 2ll * depa[i] - depa[i] - depb[i]);
    
        std::cout << ans << "\n";
    }
    
    /*
    6
    1 2 2
    1 3 0
    2 4 1
    2 5 -7
    3 6 0
    1 2 -1
    2 3 -1
    2 5 3
    2 6 -2
    3 4 8
    */
    
  • 相关阅读:
    Qt 读写XML文件
    用 Qt 中的 QDomDocument类 处理 XML 文件(上)
    Qss
    QTableWidget的使用和美工总结
    用 Qt 中的 QDomDocument类 处理 XML 文件(下)
    ArcEngine中最短路径的实现
    AE中网络分析的实现 的各个类之间的关系
    AE控制图层中要素可见状态的几种方法
    如何使用Name对象,包括WorkspaceNames和DatasetNames
    AE属性表操作
  • 原文地址:https://www.cnblogs.com/dixiao/p/15986632.html
Copyright © 2020-2023  润新知