zoukankan      html  css  js  c++  java
  • [COCI20142015#1] Kamp

    CXVI.[COCI2014-2015#1] Kamp

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

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

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

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

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

    时间复杂度\(O(n\log n)\)

    代码:

    #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;
    }
    

  • 相关阅读:
    你真的了解JSON吗?
    FormData对象
    javascript类数组
    Windows环境下XAMPP的相关设置
    PhpStorm相关设置
    yarn 与 npm 比较
    JavaScript+HTML+CSS 无缝滚动轮播图的两种方式
    javascript数据类型和类型转换
    焦大:以后seo排名核心是用户需求点的挖掘
    焦大:seo思维进化论(番外)
  • 原文地址:https://www.cnblogs.com/Troverld/p/14601347.html
Copyright © 2011-2022 走看看