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

    一、题目

    点此看题

    二、解法

    我自己做的时候用 ( t Boruvka) 加点分治,一直 ( t T) 三个点根本卡不过去。

    其实可以直接点分治,因为我们只要考虑了每条路径就考虑了每条边,那么对于每个分治中心,我们求出子树内到中心点的距离 (dis[i]),记 (p[i]=w[i]+dis[i]),找到 (p[i]) 最小的点和每个点配对即可,不需要考虑在同一个子树内的情况,因为这种边一定不优。

    那么我们通过点分治得到了 (O(nlog n)) 条边,跑 ( t kruskall) 就可以做到 (O(nlog^2n))

    如果要用 ( t Boruvka) 也可以,每次跑两遍 (dp) 处理出最优匹配点即可,时间复杂度 (O(nlog n))

    三、总结

    最小生成树还有一种重要的思路是保留有用的边。

    路径问题考虑点分治。

    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int M = 200005;
    #define int long long
    const int inf = 1e18;
    #define pii pair<int,int>
    #define mp make_pair
    #define x first
    #define y second
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,sz,tot,ans,f[M];pii rt,mi;
    int fa[M],siz[M],w[M],dis[M],vis[M];
    struct edge
    {
    	int v,c,next;
    }e[2*M];
    struct node
    {
    	int u,v,c;
    	bool operator < (const node &b) const
    	{
    		return c<b.c;
    	}
    };vector<node> v;vector<int> nw;
    void findrt(int u,int fa)
    {
    	siz[u]=1;int mx=0;
    	for(int i=f[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(vis[v] || v==fa) continue;
    		findrt(v,u);
    		siz[u]+=siz[v];
    		mx=max(mx,siz[v]);
    	}
    	mx=max(mx,sz-siz[u]);
    	rt=min(rt,mp(mx,u));
    }
    void dfs(int u,int fa)
    {
    	mi=min(mi,mp(dis[u]+w[u],u));
    	nw.push_back(u);
    	for(int i=f[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(v==fa || vis[v]) continue;
    		dis[v]=dis[u]+e[i].c;
    		dfs(v,u);
    	}
    }
    void solve(int u)
    {
    	vis[u]=1;dis[u]=0;mi=mp(inf,0);
    	nw.clear();dfs(u,u);
    	for(auto x:nw)
    		v.push_back(node{x,mi.y,mi.x+dis[x]+w[x]});
    	for(int i=f[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(vis[v]) continue;
    		rt=mp(n,0);sz=siz[v];
    		findrt(v,0);solve(rt.y);
    	}
    }
    int find(int x)
    {
    	if(fa[x]!=x) fa[x]=find(fa[x]);
    	return fa[x];
    }
    void kruskall()
    {
    	sort(v.begin(),v.end());
    	for(int i=1;i<=n;i++) fa[i]=i;
    	for(auto t:v)
    	{
    		int x=find(t.u),y=find(t.v);
    		if(x==y) continue;
    		fa[x]=y;ans+=t.c;
    	}
    }
    signed main()
    {
    	freopen("zxy.in","r",stdin);
    	n=read();
    	for(int i=1;i<=n;i++)
    		w[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		int u=read(),v=read(),c=read();
    		e[++tot]=edge{v,c,f[u]},f[u]=tot;
    		e[++tot]=edge{u,c,f[v]},f[v]=tot;
    	}
    	sz=n;rt=mp(n,0);
    	findrt(1,0);solve(rt.y);
    	kruskall();
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    架构阅读笔记4
    python读取docx内容
    python转换doc为docx
    使用Navicat连接oracle问题及解决
    扩充虚拟机磁盘
    虚拟机无法打开内核
    六个常见属性场景
    架构阅读笔记3
    架构学习
    PHP中的加密方式有如下几种
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15368901.html
Copyright © 2011-2022 走看看