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;
    }
  • 相关阅读:
    HDU 4069 Squiggly Sudoku
    SPOJ 1771 Yet Another NQueen Problem
    POJ 3469 Dual Core CPU
    CF 118E Bertown roads
    URAL 1664 Pipeline Transportation
    POJ 3076 Sudoku
    UVA 10330 Power Transmission
    HDU 1426 Sudoku Killer
    POJ 3074 Sudoku
    HDU 3315 My Brute
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764200.html
Copyright © 2011-2022 走看看