zoukankan      html  css  js  c++  java
  • bzoj 1060

    这题其实有点骗人...

    通过观察很容易发现:考虑某一些叶节点的LCA,由于根节点到这个LCA的距离唯一,故要求这些叶节点到这一LCA的距离都相等

    于是我们仅需dfs,找到次底层的节点,然后使这些节点的子节点到这些节点的距离都相等即可

    再向上回溯,算法完全相同,仅需把下面的距离累计到该节点向上的边即可

    用图理解一下:

    如图所示,所有蓝边长度应当相同,红边长度相同,绿边长度相同

    那么我们就找出蓝边中长度最长的一个,然后将所有边长变成他就可以了

    然后向上回溯:

    如图所示,将蓝边边权累计到黄边上,将红边累积到紫边上,将绿边累计到橙边上,然后令黄边,紫边,橙边长度相同即可

    贴代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    struct Edge
    {
    	int next;
    	int to;
    	int val;
    }edge[1000005];
    int head[500005];
    int dis[500005];
    int cnt=1;
    int f[500005];
    void add(int l,int r,int w)
    {
    	edge[cnt].to=r;
    	edge[cnt].next=head[l];
    	edge[cnt].val=w;
    	head[l]=cnt++;
    }
    void dfs(int x,int fx)//O(n)
    {
    	f[x]=fx;
    	for(int i=head[x];i!=-1;i=edge[i].next)
    	{
    		int to=edge[i].to;
    		if(to==fx)
    		{
    			continue;
    		}
    		dfs(to,x);
    	}
    }
    ll tot=0;
    void dfs2(int rt,int frt)//O(n*log2n)
    {
    	for(int i=head[rt];i!=-1;i=edge[i].next)//O(n*log2n)
    	{
    		int to=edge[i].to;
    		if(to==frt)
    		{
    			continue;
    		}
    		dfs2(to,rt);
    	}
    	priority_queue <int> M;
    	for(int i=head[rt];i!=-1;i=edge[i].next)//O(log2n)
    	{
    		int to=edge[i].to;
    		if(to==frt)
    		{
    			continue;
    		}
    		M.push(edge[i].val);
    	}
    	if(!M.empty())
    	{
    		int l=M.top();
    		M.pop();
    		while(!M.empty())//O(n*log2n)
    		{
    			int l1=M.top();
    			M.pop();
    			tot+=(ll)l-l1;
    		}
    		for(int i=head[frt];i!=-1;i=edge[i].next)
    		{
    			int to=edge[i].to;
    			if(to==rt)
    			{
    				edge[i].val+=l;
    				break;
    			}
    		}
    	}
    }
    int main()
    {
    	memset(head,-1,sizeof(head));
    	int n;
    	scanf("%d",&n);
    	int rt;
    	scanf("%d",&rt);
    	for(int i=1;i<n;i++)
    	{
    		int x,y,v;
    		scanf("%d%d%d",&x,&y,&v);
    		add(x,y,v);
    		add(y,x,v);
    	}
    	dfs(rt,rt);
    	dfs2(rt,rt);
    	printf("%lld
    ",tot);
    	return 0;
    }
  • 相关阅读:
    web.xml文件详解
    SQLSERVER dbo解释
    sqlserver BULK INSERT
    google 基站定位api
    Sqlserver中Select和Set区别
    SQL Server优化50法
    ibatis常用16条SQL
    面向对象 -- 三大特性之继承 补充 抽象类 接口类
    面向对象 -- 三大特性之继承
    面向对象 -- 类的组合
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764200.html
Copyright © 2011-2022 走看看