[COCI2014-2015#1] Kamp

CXVI.[COCI2014-2015#1] Kamp

一看题面,突然感觉很弱智,不就是求出以每个点为根到其它所有特殊点的距离之和吗?这不是随随便便换个根就完事了吗?

然后兴冲冲敲出来,一测样例全挂。

后来发现并不是这样的,因为车上可以同时搭载多人,且车最后可以就停在某个地方不回去了。

稍微想想可以发现,最终停着的位置,一定是离起点最远的特殊点;故我们直接使用 multiset 维护一下就可以换根了。求出每个节点离其最远的特殊点的距离后,以它为根的答案就是(从它出发到达所有点再回到它的最短距离)(上述DP值)

然后,因为车上可以搭载多人,所以实际上上述最短距离就是二倍以当前点和所有特殊点构成的虚树大小。这个可以直接通过求虚树大小的做法(按照dfs序排序再求出两两相邻点间距离)或者干脆直接再来一发换根解决。

时间复杂度O(nlogn)

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,head[500100],cnt,g[500100];
ll f[500100],h[500100];
bool sp[500100];
struct node{
	int to,next,val;
}edge[1001000];
void ae(int u,int v,int w){
	edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
	edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=w,head[v]=cnt++;
}
multiset<ll>s[500100];
void dfs1(int x,int fa){
	if(sp[x])g[x]++,h[x]=0,s[x].insert(0);
	for(int i=head[x],y;i!=-1;i=edge[i].next){
		if((y=edge[i].to)==fa)continue;
		dfs1(y,x),f[x]+=f[y]+1ll*!!g[y]*edge[i].val,g[x]+=g[y];
		h[x]=max(h[x],h[y]+edge[i].val),s[x].insert(h[y]+edge[i].val);
	}
}
void dfs2(int x,int fa){
	for(int i=head[x],y;i!=-1;i=edge[i].next){
		if((y=edge[i].to)==fa)continue;
		ll fx=f[x]-f[y]-1ll*!!g[y]*edge[i].val;
		int gx=g[x]-g[y];
		f[y]+=fx+1ll*!!gx*edge[i].val;
		g[y]+=gx;
		
		s[x].erase(s[x].find(h[y]+edge[i].val));
		if(!s[x].empty())s[y].insert(*s[x].rbegin()+edge[i].val);
		s[x].insert(h[y]+edge[i].val);
		h[y]=*s[y].rbegin();
		
		dfs2(y,x);
	}
}
int main(){
	scanf("%d%d",&n,&m),memset(head,-1,sizeof(head)),memset(h,0xc0,sizeof(h));
	for(int i=1,x,y,z;i<n;i++)scanf("%d%d%d",&x,&y,&z),ae(x,y,z);
	for(int i=1,x;i<=m;i++)scanf("%d",&x),sp[x]=true;
	dfs1(1,0),dfs2(1,0);
//	for(int i=1;i<=n;i++)printf("%lld %d %lld\n",f[i],g[i],h[i]);
	for(int i=1;i<=n;i++)printf("%lld\n",2*f[i]-h[i]); 
	return 0;
}

posted @   Troverld  阅读(103)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示