• Kruskal重构树(货车运输)


    。。。
    和Kruskal生成树一样

    本来是u,v连一条f的边

    现在变成新建一个点,点权为f,u v都像它连无边权的边

    (实际上应该是u的根和v的根)

    这样树有一些性质:

    1.二叉树

    2.原树与新树两点间路径上边权(点权)的最大(最小)值相等

    3.子节点的边权(大于等于)小于等于父亲节点

    4.原树中两点之间路径上边权的最大(最小)值等于新树上两点的LCA的点权

    # include <iostream>
    # include <stdio.h>
    # include <stdlib.h>
    # include <algorithm>
    # include <string.h>
    # define IL inline
    # define ll long long
    # define Fill(a, b) memset(a, b, sizeof(a));
    using namespace std;
    
    IL ll Read(){
        char c = '%'; ll x = 0, z = 1;
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
        return x * z;
    }
    
    const int MAXN = 20001, MAXM = 200001;
    int ft[MAXN], n, m, cnt, fa[MAXN][20], w[MAXN], deep[MAXN], Fa[MAXN], num;
    struct Edge{
        int to, nt;
    } edge[MAXM];
    struct Kruskal{
        int u, v, f;
        IL bool operator <(Kruskal b) const{
            return f > b.f;
        }
    } road[MAXM];
    
    IL int Find(int x){
        return Fa[x] == x ? x : Fa[x] = Find(Fa[x]);
    }
    
    IL void Add(int u, int v){
        edge[cnt] = (Edge){v, ft[u]}; ft[u] = cnt++;
        edge[cnt] = (Edge){u, ft[v]}; ft[v] = cnt++;
    }
    
    IL void Dfs(int u){
        for(int e = ft[u]; e != -1; e = edge[e].nt){
            int v = edge[e].to;
            if(!deep[v]){
                deep[v] = deep[u] + 1;
                fa[v][0] = u;
                Dfs(v);
            }
        }
    }
    
    IL int LCA(int u, int v){
        if(Find(u) != Find(v)) return -1;
        if(deep[u] < deep[v]) swap(u, v);
        for(int i = 18; i >= 0; i--)
            if(deep[fa[u][i]] >= deep[v]) u = fa[u][i];
        if(u == v) return w[u];
        for(int i = 18; i >= 0; i--)
            if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
        return w[fa[u][0]];
    }
    
    int main(){
        Fill(ft, -1);
        num = n = Read(); m = Read();
        for(int i = 1; i <= 2 * n; i++)
            Fa[i] = i;
        for(int i = 1; i <= m; i++)
            road[i] = (Kruskal){Read(), Read(), Read()};
        sort(road + 1, road + m + 1);
        for(int i = 1, tot = 0; i <= m && tot < n; i++){
            int u = Find(road[i].u), v = Find(road[i].v);
            if(u != v){
                tot++;
                w[++num] = road[i].f;
                Fa[u] = Fa[v] = num;
                Add(u, num); Add(v, num);
            }
        }
        for(int i = num; i; i--)
            if(!deep[i]) deep[i] = 1, Dfs(i);
        for(int i = 1; i <= 18; i++)
            for(int j = 1; j <= num; j++)
                fa[j][i] = fa[fa[j][i - 1]][i - 1];
        int Q = Read();
        while(Q--){
            int u = Read(), v = Read();
            printf("%d
    ", LCA(u, v));
        }
        return 0;
    }
  • 相关阅读:
    sql server紧急状态下登录脚本
    将SQL for xml path('')中转义的字符正常显示
    SQL查询表中的有那些索引
    Set ARITHABORT Option设置为ON
    检测重编译
    计划指南
    sql server 清理缓存
    变量绑定
    分析及动态采样
    Hint
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8206402.html
Copyright © 2020-2023  润新知