列表

详情


NC20581. [SDOI2015]寻宝游戏

描述

小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达。
游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。
小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。
但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小B需要不断地更新数据,但是小B太懒了,不愿意自己计算,因此他向你求助。
为了简化问题,我们认为最开始时所有村庄内均没有宝物

输入描述

第一行,两个整数N、M,其中M为宝物的变动次数。
接下来的N-1行,每行三个整数x、y、z,表示村庄x、y之间有一条长度为z的道路。
接下来的M行,每行一个整数t,表示一个宝物变动的操作。
若该操作前村庄t内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

输出描述

M行,每行一个整数,其中第i行的整数表示第i次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出0。

示例1

输入:

4 5
1 2 30
2 3 50
2 4 60
2
3
4
2
1

输出:

0
100
220
220
280

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 229ms, 内存消耗: 20012K, 提交时间: 2021-09-15 21:42:26

#include<bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=1e5+5;
typedef long long ll;
struct edge{
	int v;
	int nxt;
	ll w;
}e[N<<1];
int cnt=0,head[N],dep[N],dfn[N],df=0,vis[N],f[N][20];
ll len[N];
void addedge(int u,int v,ll w){
	e[++cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt;
} 
/*
维护一个深度数组 一个点到根节点距离的数组 
*/
void dfs(int u,int fa){
	dfn[u]=++df;
	f[u][0]=fa;
	for(int i=1;i<=19;i++){
		f[u][i]=f[f[u][i-1]][i-1];
	}
	for(int i=head[u];~i;i=e[i].nxt){
		int v=e[i].v;
		if(v==fa)continue;
		len[v]=len[u]+e[i].w;
		dep[v]=dep[u]+1;
		dfs(v,u);
	}
}
set<pii> s;
int lca(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int i=19;i>=0;i--){
		if(dep[f[x][i]]<dep[y])continue;
		else x=f[x][i];
	}
	if(x==y)return x;
	for(int i=19;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];y=f[y][i];
		}
	}
	return f[x][0];
}
ll dis(int x,int y){
	return len[x]+len[y]-2*len[lca(x,y)];
}
int getl(int x){
	auto it=s.find(mp(dfn[x],x));
	if(it==s.begin())it=s.end();
	--it;
	return (*it).se;
}
int getr(int x){
	auto it=s.find(mp(dfn[x],x));
	if(++it==s.end())it=s.begin();
	return (*it).se;
}
int main(){
	int n,m;
	cin>>n>>m;
	memset(head,-1,sizeof head);
	for(int i=1;i<n;i++){
		int x,y;
		ll z;
		scanf("%d%d%lld",&x,&y,&z);
		addedge(x,y,z);
		addedge(y,x,z);
	}
	dfs(1,1);
	ll ans=0;
	for(int i=1;i<=m;i++){
		int x;
		scanf("%d",&x);
		if(!vis[x]){
			s.insert(mp(dfn[x],x));
			int l=getl(x),r=getr(x);
			ans+=dis(l,x)+dis(x,r)-dis(l,r);
		}
		else {
			int l=getl(x),r=getr(x);
			ans+=dis(l,r)-dis(x,r)-dis(l,x);
			s.erase(mp(dfn[x],x));
		}
		vis[x]^=1;
		printf("%lld\n",ans);
	}
	return 0;
} 

上一题