zoukankan      html  css  js  c++  java
  • H

    H - Traveling Plan 最小生成树+路径的最大值

    这个题目太可惜了,想错了一点点,本来是想把0的点都删去,但是想了好久都不知道怎么删,最后看了题解发现可以不用删边,把边的大小变成等效删边的大小即可

    题解:
    参考题目:lh的简单图论

    多源最短路求出每一个点到最近的补给点的距离 $d[i] $

    那么,任意两条边的距离就更新为:(d[x]+d[y]+w)

    然后就是最小生成树将图转化成树,最后就是用倍增的LCA顺便求一下最大值。

    [红蓝图](https://ac.nowcoder.com/acm/contest/7745/F)  kruskal重构树+dfs序+线段树合并
    
    题解:
    
    如果不会kruskal重构树,建议先写 [D. Graph and Queries 并查集+线段树+kruskal重构树](https://www.cnblogs.com/EchoZQN/p/13804989.html)   
    
    * 首先对查询按照 t  从大到小排序,然后按照权值从大到小建一棵kruskal重构树,然后dfs求出每一个节点的dfs序,顺便求出每一个询问节点的子树节点。
    * 对于每一个节点都建一棵动态开点的线段树,然后对查询按照 t 从小到大排序,边建线段树边输出询问。
    
    ​~~~c++
    #include <bits/stdc++.h>
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e5+10;
    typedef long long ll;
    struct node{
        int u,v;
        ll w;
        node(int u=0,int v=0,ll w=0):u(u),v(v),w(w){}
    }e[maxn];
    int a[maxn],Head[maxn],To[maxn<<1],Nxt[maxn<<1],CNT;
    ll w[maxn<<1];
    void add(int u,int v,int c){
        ++CNT,To[CNT]=v,Nxt[CNT]=Head[u],w[CNT]=c,Head[u]=CNT;
        ++CNT,To[CNT]=u,Nxt[CNT]=Head[v],w[CNT]=c,Head[v]=CNT;
    }
    struct heapnode{
        int u;
        ll d;
        heapnode(int u=0,ll d=0):u(u),d(d){}
        bool operator<(const heapnode& a)const{
            return a.d<d;
        }
    };
    priority_queue<heapnode>que;
    ll dis[maxn];
    bool vis[maxn];
    int f[maxn];
    int find(int x){
        return f[x]==x?x:f[x] = find(f[x]);
    }
    void unite(int x,int y){
        x = find(x),y = find(y);
        if(x == y) return ;
        f[x] = y;
    }
    bool same(int x,int y){
        return find(x)==find(y);
    }
    
    int head[maxn],to[maxn<<1],cost[maxn<<1],nxt[maxn<<1],cnt;
    void ADD(int u,int v,int w){
        ++cnt,to[cnt]=v,cost[cnt]=w,nxt[cnt]=head[u],head[u]=cnt;
        ++cnt,to[cnt]=u,cost[cnt]=w,nxt[cnt]=head[v],head[v]=cnt;
    }
    
    bool cmp(node a,node b){
        return a.w<b.w;
    }
    
    ll gw[maxn][22];
    int fa[maxn][22],dep[maxn];
    void dfs(int u,int pre,int deep){
        fa[u][0] = pre,dep[u] = deep;
        // printf("u = %d pre = %d deep=%d
    ", u,pre,deep);
        for(int i=head[u];i;i=nxt[i]){
            int v = to[i];
            if(v == pre) continue;
            gw[v][0] = cost[i];
            dfs(v,u,deep+1);
        }
    }
    
    void init(int n){
        for(int j=1;(1<<j)<=n;j++){
            for(int i=1;i<=n;i++){
                fa[i][j] = fa[fa[i][j-1]][j-1];
                gw[i][j] = max(gw[i][j-1],gw[fa[i][j-1]][j-1]);
            }
        }
    }
    int n,m;
    ll LCA(int u,int v){
        ll ans = 0;
        if(dep[u]<dep[v]) swap(u,v);
        int d = dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if((1<<i)&d) {
                ans = max(ans,gw[u][i]);
                u = fa[u][i];
            }
        }
        for (int i = (int)log(n); i >= 0; i--){//一起往上走
            if(fa[u][i]!=fa[v][i]){
                ans = max(ans, gw[u][i]);
                ans = max(ans, gw[v][i]);
                u = fa[u][i];
                v = fa[v][i];
            }
        }
        if(u!=v){ //最后一步
            ans = max(ans, gw[u][0]);
            ans = max(ans, gw[v][0]);
        }
        return ans;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            if(a[i]==1) que.push(heapnode(i,0));
            else dis[i] = inf64;
            f[i] = i;
        }
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            e[i] = node(u,v,w);
            add(u,v,w);
        }
        while(!que.empty()){
            heapnode x = que.top();que.pop();
            int u = x.u;
            if(vis[u]) continue;
            vis[u] = true;
            for(int i=Head[u];i;i=Nxt[i]){
                int v = To[i];
                if(dis[v]>dis[u]+w[i]){
                    dis[v] = dis[u] + w[i];
                    que.push(heapnode(v,dis[v]));
                }
            }
        }
        // for(int i=1;i<=n;i++){
        //     printf("dis[%d]=%lld
    ", i,dis[i]);
        // }
        for(int i=1;i<=m;i++) {
            e[i].w += dis[e[i].u]+dis[e[i].v];
            // printf("e[%d].z=%lld
    ", i,e[i].w);
        }
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=m;i++){
            int u = e[i].u,v = e[i].v;
            if(same(u,v)) continue;
            unite(u,v);
            ADD(u,v,e[i].w);
        }
        dfs(1,0,1),init(n);
        int q;
        scanf("%d",&q);
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            ll ans = LCA(x,y);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
    ​~~~
    
    
    
  • 相关阅读:
    《一个医生的故事》:协和妇产科主任文艺散文集,三星
    《睡眠正能量》:《正能量》作者关于睡眠的科学研究的科普与综述,三星
    [miniApp] WeChat user login code
    [Vue @Component] Pass Vue Render Functions as Props for Powerful Patterns
    [Vue @Component] Write Vue Functional Components Inline
    [Vue @Component] Control Template Contents with Vue's Render Function
    [Vue @Component] Pass Props to Vue Functional Templates
    [JavaEE] Bootstrapping a JavaEE Application
    [Vue @Component] Place Content in Components with Vue Slots
    [Vue @Component] Define Props on a Vue Class with vue-property-decorator
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13811131.html
Copyright © 2011-2022 走看看