首页 > 其他分享 >P6805 (树上最小路径覆盖思想)

P6805 (树上最小路径覆盖思想)

时间:2024-02-27 10:00:55浏览次数:22  
标签:rt int sum 路径 mid 100005 P6805 树上 size

难度3

比较有意思的一道题。首先看到题目是求树上最小路径覆盖,自然想到由叶子入手去分析,所以当子树内有偶数个叶子节点时,那么就有两个叶子向上匹配,否则只有一个叶子向上匹配。这个东西可以用树剖维护,线段树维护的是子树内有多少个偶的,相当于一个区间反转一类的东西。

细节不算多,但也坑了我0.5h,以后在检查时要想好这句话在什么情况下运行,有什么影响,而不是大眼瞪小眼。

#include<bits/stdc++.h>
using namespace std;
int n,T,rt,x,y,tot,a[100005],g[100005],cnt=0;
int dep[100005],fa[100005],val[100005],size[100005],sum[100005],son[100005],top[100005],id[100005]; 
int d[400005],la[400005];
bool vis[100005];
vector<int>v[100005];
void dfs1(int u,int from){
	fa[u]=from;
	size[u]=1;
	if(v[u].size()==1) sum[u]=1;
	dep[u]=dep[from]+1;
	int maxx=-1;
	for(int i=0;i<v[u].size();i++){
		int to=v[u][i];
		if(to!=from){
			dfs1(to,u);
			if(size[to]>maxx){
				maxx=size[to];
				son[u]=to;
			}
			size[u]+=size[to];
			sum[u]+=sum[to];
		}
	}
}
void dfs2(int u,int from,int utop){
	cnt++;
	id[u]=cnt;
	if(sum[u]%2==0) val[cnt]=1;
	top[u]=utop;
	if(son[u]) dfs2(son[u],u,utop); 
	for(int i=0;i<v[u].size();i++){
		int to=v[u][i];
		if(to!=from&&to!=son[u]){
			dfs2(to,u,to);
		}
	}
}
void push_down(int l,int r,int p,int mid){
	if(la[p]){
		d[p<<1]=(mid-l+1)-d[p<<1];
		d[p<<1|1]=(r-mid)-d[p<<1|1];
		la[p<<1]=!la[p<<1];
		la[p<<1|1]=!la[p<<1|1];
		la[p]=0;
	}
}
void push_up(int p){
	d[p]=d[p<<1]+d[p<<1|1];
}
void build(int l,int r,int p){
	if(l==r){
		d[p]=val[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,p<<1);
	build(mid+1,r,p<<1|1);
	push_up(p);
}
void update(int l,int r,int p,int s,int t){
	if(l>=s&&r<=t){
		d[p]=(r-l+1)-d[p];
		la[p]=!la[p];
		return;
	}
	int mid=(l+r)>>1;
	push_down(l,r,p,mid);
	if(s<=mid) update(l,mid,p<<1,s,t);
	if(t>mid) update(mid+1,r,p<<1|1,s,t);
	push_up(p);
}
int getsum(int l,int r,int p,int s,int t){
	if(l>=s&&r<=t){
		return d[p];
	}
	int mid=(l+r)>>1,ans=0;
	push_down(l,r,p,mid);
	if(s<=mid) ans+=getsum(l,mid,p<<1,s,t);
	if(t>mid) ans+=getsum(mid+1,r,p<<1|1,s,t);
	return ans;
}
void update1(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		update(1,n,1,id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y); 
	update(1,n,1,id[x],id[y]);
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>T;
	for(int i=1;i<=n-1;i++){
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(v[i].size()>=2){
			rt=i;
			break;
		}
	}
	dfs1(rt,0);
	dfs2(rt,0,rt);
	build(1,n,1);
	tot=sum[rt];
	while(T--){
		int leaf=0;
		cin>>x;
		for(int i=1;i<=x;i++){
			cin>>a[i];
			if(vis[a[i]]==false&&v[a[i]].size()==1) leaf++; 
			else{
				update1(rt,a[i]);
				g[i]=1;
			}
			vis[a[i]]=true;
		}
		if((tot+x-leaf)%2==1) cout<<"-1\n";
		else cout<<n+x-2+getsum(1,n,1,1,n)<<"\n"; 
		for(int i=1;i<=x;i++){
			if(g[i]==1){
				update1(rt,a[i]);
				g[i]=0;
			}
			vis[a[i]]=false;
		}
	}
	
	return 0;
}

标签:rt,int,sum,路径,mid,100005,P6805,树上,size
From: https://www.cnblogs.com/wuhupai/p/18036255

相关文章

  • SpringBoot:通过实现自定义接口获取实现类的@RequestMapping注解请求路径
    1.自定义接口//什么都不用写,就定义一个空接口publicinterfaceMyMark{}2.Controller接口类实现自定义接口@RestControllerpublicclassDayControllerimplementsMyMark{@RequestMapping("/day1")publicStringget1(){return"day1";}......
  • 路径
    前端路径问题相对路径背景:图片存在项目/sataic/img文件夹下面三种情况当html文件与static文件夹同级,直接src="satic/img/logo.png"当html不与static文件夹同级,则需要用../来抵消当前url的后缀,再拼接src="satic/img/logo.png"WEB-INF文件夹下的html文件要引用img里的图片:首......
  • 洛谷 P4198 楼房重建(线段树上二分)
    传送门解题思路动态维护区间里面单调递增斜率的长度需要维护两个信息:上述长度,和区间最大值(合并时需要)难点在于两个子区间的合并。左区间的楼房一定都能看见(没有遮挡),所以要在右区间二分,找到左面最大值lmax在右区间的位置,然后进行合并。复杂度两个log。AC代码#include<ios......
  • git中的中文路径显示
    在设置了git控制台编码格式为utf-8后,分别是gitgui工具,commit、log的默认编码:gitconfig--globalgui.encodingutf-8gitconfig--globali18n.commitencodingutf-8gitconfig--globali18n.logoutputencodingutf-8那么在使用gitlog、gitstatus时,会有如下的情况:"M......
  • everything指定搜索路径
    1.在搜索选项里选择“匹配路径”,其他不要选,如下: 2.先指定路径。如只搜索F盘则输入F:\,后面再输入需要的内容,如找F盘里的冒泡: 3.例:只搜索E盘vscode文件夹,则先指定E:\vscode,再输入需要找的东  ......
  • leedcode 路径的和
    使用迭代:classSolution:defhasPathSum(self,root:Optional[TreeNode],targetSum:int)->bool:#如果根节点为空,直接返回Falseifnotroot:returnFalse#使用栈来进行迭代,每个元素是一个元组(node,path)stack=......
  • day39 动态规划part2 代码随想录算法训练营 63. 不同路径 II
    题目:63.不同路径II我的感悟:题目不难,就是不知道哪个煞笔,把路拦截死了,并且入口就放石头,我真是吐了。理解难点:初始值的遇到障碍要Break其他我写的没错边界考虑:还有入口和出口有障碍物的话,要直接返回0.听课笔记:差不多,考虑的点就是:初始值后面为break开头和结尾有障......
  • Linux-Source Insight添加系统库路径
    1、在BASE项目下添加Project->OpenProject,打开Base项目2、打开PreferencesProject->Preferences,选择SymbolLookups选项卡3、打开ImportSymbolsforAllProjects4、打开右侧Add按钮,弹出AddExternalSymbols对话框5、打开ImportfromanINCLUDEpath6、将需要添加的......
  • 树上dp——cf_928_G. Vlad and Trouble at MIT
    目录问题概述思路分析参考代码做题反思问题概述原题参考:G.VladandTroubleatMIT某学校的宿舍可以用一棵n个顶点的树来表示,每个顶点代表一个房间,房间内有一个学生,树是一个联通的无向图。今天晚上有三种学生:参加派对和玩音乐的学生(标记为P)想睡觉和享受安静的学生(标记为S)......
  • 力扣 dfs之 437. 路径总和 III
    给定一个二叉树的根节点root ,和一个整数targetSum,求该二叉树里节点值之和等于targetSum的路径的数目。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。 示例1:输入:root=[10,5,-3,3,2,null,11,3,-2,null,1],target......