ESD en te los temas relacionados con el ejercicio (DFS)

ESD en te los temas relacionados con el ejercicio (DFS)

Aquí Insertar imagen Descripción

1.U41492 número de colores en los árboles

Aquí Insertar imagen Descripción
ESD en el árbol desnudo título, específicamente para ver el Código

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
vector<int>v[N];
int col[N],hev[N],sz[N],cnt[N],mx,son,n;
ll sum,ans[N];
void dfs1(int u,int fa){
	sz[u]=1;
	for(int i=0;i<v[u].size();i++)
	{
		int to=v[u][i];
		if(to!=fa)
		{
			dfs1(to,u);
			sz[u]+=sz[to];
			if(sz[to]>sz[hev[u]]) hev[u]=to;//更新轻重链部分 
		}
	}
}
void add(int u,int fa,int val){
	 //printf("u=%d,fa=%d,val=%d\n",u,fa,val); 
	 cnt[col[u]]+=val;
	 if(val==1&&cnt[col[u]]==1) sum++; ///根据题目要求修改。 
	 else if(val==-1&&cnt[col[u]]==0) sum--; 
	 for(int i=0;i<v[u].size();i++){
	 	  int to=v[u][i];
	 	  if(to!=fa&&to!=son) //统计所有轻儿子贡献。 
	 	  	add(to,u,val);
	 }
}
void dfs2(int u,int fa,int opt){ //opt表示十分消除贡献  0表示消除,1表示不消除 
	 //printf("u=%d,fa=%d,opt%d\n",u,fa,opt); 
	 for(int i=0;i<v[u].size();i++)
	 {
	 	 int to=v[u][i];
	 	 if(to!=fa&&to!=hev[u])
	 	 		dfs2(to,u,0);//搜索所有轻边,递归完成后消除对该点的影响 
	 }
	 if(hev[u]) dfs2(hev[u],u,1),son=hev[u];//搜索重边,且不消除影响。 
	 //最后搜索重边不删除影响   叶子结点没有轻儿子,相当于自己就是轻儿子。下面的add(u,fa,1)就是加上自己 
	 add(u,fa,1),son=0;//暴力统计所有轻儿子的贡献    
	 ans[u]=sum;
	 if(!opt) add(u,fa,-1),sum=mx=0;//如果不是重儿子就消除影响,如果是重儿子(最后搜索)就保存影响。最后直接加上轻儿子的贡献就是总贡献 
} 
int main(){
	cin>>n;
	for(int i=1,a,b;i<=n-1;i++)
	{
		cin>>a>>b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	for(int i=1;i<=n;i++) cin>>col[i];
	dfs1(1,0);
	dfs2(1,0,0);
	for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
	return 0;
}

2.E. gelral Lomsat

título de la plantilla CF600E

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
vector<int>v[N];
int col[N],hev[N],sz[N],cnt[N],mx,son,n;
ll sum,ans[N];
void dfs1(int u,int fa){
	sz[u]=1;
	for(int i=0;i<v[u].size();i++)
	{
		int to=v[u][i];
		if(to!=fa)
		{
			dfs1(to,u);
			sz[u]+=sz[to];
			if(sz[to]>sz[hev[u]]) hev[u]=to;//更新轻重链部分 
		}
	}
}
void add(int u,int fa,int val){
	 //printf("u=%d,fa=%d,val=%d\n",u,fa,val); 
	 cnt[col[u]]+=val;  ///这一块根据题目具体要求修改 
	 if(cnt[col[u]]>mx) mx=cnt[col[u]],sum=col[u];
	 else if(cnt[col[u]]==mx) sum+=(ll)col[u];
	 for(int i=0;i<v[u].size();i++){
	 	  int to=v[u][i];
	 	  if(to!=fa&&to!=son) //统计所有轻儿子贡献。 
	 	  	add(to,u,val);
	 }
}
void dfs2(int u,int fa,int opt){ //opt表示十分消除贡献  0表示消除,1表示不消除 
	 printf("u=%d,fa=%d,opt%d\n",u,fa,opt); 
	 for(int i=0;i<v[u].size();i++)  ////搜索n个结点复杂度 O(n) 任意点到根的路径最多有logn个轻边 重边不用删除 所以时间复杂度为O(nlogn) 
	 {
	 	 int to=v[u][i];
	 	 if(to!=fa&&to!=hev[u])
	 	 		dfs2(to,u,0);//搜索所有轻边,递归完成后消除对该点的影响 
	 }
	 if(hev[u]) dfs2(hev[u],u,1),son=hev[u];//搜索重边,且不消除影响。 
	 //最后搜索重边不删除影响   叶子结点没有轻儿子,相当于自己就是轻儿子。下面的add(u,fa,1)就是加上自己 
	 add(u,fa,1),son=0;//暴力统计所有轻儿子的贡献    
	 ans[u]=sum;
	 if(!opt) add(u,fa,-1),sum=mx=0;//如果不是重儿子就消除影响,如果是重儿子(最后搜索)就保存影响。最后直接加上轻儿子的贡献就是总贡献 
} 
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>col[i];
	for(int i=1,a,b;i<=n-1;i++)
	{
		cin>>a>>b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	dfs1(1,0);
	dfs2(1,0,0);
	for(int i=1;i<=n;i++) printf(i==n?"%lld\n":"%lld ",ans[i]);
	return 0;
}
Publicado 25 artículos originales · ganado elogios 19 · vistas 787

Supongo que te gusta

Origin blog.csdn.net/weixin_45750972/article/details/105159216
Recomendado
Clasificación