【AT3611】Tree MST

topic

Enter the title of the first is a tree, we consider dotted

We consider the center of gravity for each partition it across the divide and conquer even the edge of the center of gravity of the situation

It is to divide and conquer all of the center of gravity from the current partition area closest point even edge

Consider the correctness of the algorithm, if we have a link to an internal block forming a \ (mst \) , we need to link this block and another block Unicom merger

If the new block appears Unicom China Unicom will make the original block \ (mst \) change, then the side will only emerging China Unicom is the original point of the block and the block to the side of the new interchange point between the nearest point , and yet these are the nearest point a, so we can greatly simplify the number of connected edge

So this process is equivalent dotted merger \ (mst \) process

After we discovered we even dotted about the \ (nlogn \) edges, so kruskal like a rerun, complexity \ (O (nlog ^ 2n) \)

Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=2e5+5;
struct E{int v,nxt,w;}e[maxn<<1];
struct Edge{int a,b;LL c;}E[maxn*55];
int sum[maxn],vis[maxn],head[maxn],mx[maxn],a[maxn],fa[maxn],sz[maxn];
int n,num,m,dx,S,rt;LL dw,ans,pre[maxn];
inline void add(int x,int y,int z) {
    e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=z;
}
void getroot(int x,int fa) {
    sum[x]=1,mx[x]=0;
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[e[i].v]||e[i].v==fa) continue;
        getroot(e[i].v,x);sum[x]+=sum[e[i].v];
        mx[x]=max(mx[x],sum[e[i].v]);
    }
    mx[x]=max(mx[x],S-sum[x]);
    if(mx[x]<mx[rt]) rt=x;
}
void getdis(int x,int fa) {
    E[++m]=(Edge){dx,x,pre[x]+a[x]+dw};
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[e[i].v]||e[i].v==fa) continue;
        getdis(e[i].v,x);
    }
}
void chk(int x,int fa) {
    if(pre[x]+a[x]<dw) dw=pre[x]+a[x],dx=x;
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[e[i].v]||e[i].v==fa) continue;
        pre[e[i].v]=pre[x]+e[i].w;chk(e[i].v,x);
    }
}
void dfs(int x) {
    dx=x,dw=a[x];vis[x]=1;pre[x]=0,chk(x,0),getdis(x,0);
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[e[i].v]) continue;
        S=sum[e[i].v],rt=0,getroot(e[i].v,0),dfs(rt);
    }
}
inline int cmp(Edge A,Edge B) {return A.c<B.c;}
inline int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
inline int merge(int x,int y) {
    int xx=find(x),yy=find(y);
    if(xx==yy) return 0;
    if(sz[xx]<sz[yy]) fa[xx]=yy,sz[yy]+=sz[xx];
        else fa[yy]=xx,sz[xx]+=sz[yy];
    return 1;
}
int main() {
    n=read();
    for(re int i=1;i<=n;i++) a[i]=read();
    for(re int x,y,z,i=1;i<n;i++) 
        x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z); 
    mx[0]=n+1,S=n,rt=0,getroot(1,0),dfs(rt);
    std::sort(E+1,E+m+1,cmp);
    for(re int i=1;i<=n;i++) sz[i]=1,fa[i]=i;
    for(re int i=1;i<=m;i++) if(merge(E[i].a,E[i].b)) ans+=E[i].c;
    std::cout<<ans;
    return 0;
}

Guess you like

Origin www.cnblogs.com/asuldb/p/10977498.html
MST
MST