zoukankan      html  css  js  c++  java
  • AtCoder3611 Tree MST

    题目描述

    题解

    不可能把完全图的边都找出来,需要考虑能否删去一些边使其与完全图的 $ ext{mst}$ 相同。

    有 $ ext{dis}$ 我们可以考虑点分治,即对于一个点分中心,如果有三个点 $x,y,z$ ,如果 $W(x,y) le W(y,z)$ 并且 $W(x,z) le W(y,z)$ ,那我们在做 $ ext{mst}$ 的时候肯定不会加上 $W(y,z)$ 这一条边。

    所以我们可以找到 $W(x,rt)$ 最小的 $x$ ,然后每个点都和 $x$ 相连,这样得到的图的 $ ext{mst}$ 是等效于原来的完全图的,而这张图的边数是 $O(nlogn)$ 的,所以总效率为 $O(nlog^2n)$ 。

    代码

    #include <bits/stdc++.h>
    #define I inline
    #define LL long long
    using namespace std;
    const int N=2e5+5;bool vis[N];LL G,s;
    int n,m,X,f[N],sz[N],son[N],rt,o,hd[N],V[N*2],a[N],W[N*2],nx[N*2],t;
    struct O{int u,v;LL w;}p[N*50];
    int get(int x){return x==f[x]?x:f[x]=get(f[x]);}
    I void add(int u,int v,int w){
        nx[++t]=hd[u];V[hd[u]=t]=v;W[t]=w;
    }
    #define v V[i]
    I void getrt(int x,int fa){
        sz[x]=1;son[x]=0;
        for (int i=hd[x];i;i=nx[i])
            if (v!=fa && !vis[v])
                getrt(v,x),sz[x]+=sz[v],
                son[x]=max(son[x],sz[v]);
        son[x]=max(o-sz[x],son[x]);
        if (son[x]<son[rt]) rt=x;
    }
    I void find(int u,int fa,LL w){
        if (w+a[u]<G) G=w+a[u],X=u;
        for (int i=hd[u];i;i=nx[i])
            if (!vis[v] && v!=fa)
                find(v,u,w+W[i]);
    }
    I void ins(int u,int fa,LL w){
        p[++m]=(O){u,X,G+w+a[u]};
        for (int i=hd[u];i;i=nx[i])
            if (!vis[v] && v!=fa)
                ins(v,u,w+W[i]);
    }
    I void work(int x){
        vis[x]=1;G=2e18;X=0;
        find(x,0,0ll);ins(x,0,0ll);
        for (int i=hd[x];i;i=nx[i])
            if (!vis[v]) rt=0,o=sz[v],
                getrt(v,x),work(rt);
    }
    #undef v
    bool cmp(O A,O B){return A.w<B.w;}
    int main(){
        son[0]=1e9;
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]),f[i]=i;
        for (int x,y,z,i=1;i<n;i++)
            scanf("%d%d%d",&x,&y,&z),
            add(x,y,z),add(y,x,z);
        t=0;o=n;getrt(1,0);work(rt);
        sort(p+1,p+m+1,cmp);
        for (int u,v,i=1;i<=m;i++){
            u=get(p[i].u);v=get(p[i].v);
            if (u!=v) s+=p[i].w;f[u]=v;
        }
        cout<<s<<endl;return 0;
    }
  • 相关阅读:
    编写高质量代码建议17代码错误调试
    同步和异步的不同场景的概念理解
    kafka版本0.8.2.0-Producer Configs之request.required.acks
    linux的grep命令
    jetty服务器访问系统的域名
    linux工具问题,tail -f 失效
    memcached并发处理
    python爬虫scrapy的Selectors参考文档
    访问nginx提示gateway timeout 504 ,发现总是当调用时间超过30s时提示504错误
    重构再次理解
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12437034.html
Copyright © 2011-2022 走看看