Connecting...

Blood Cousins Return 解题报告

为了体现我29买的typora的价值,本文用typora编辑

题目链接

[E. Blood Cousins Return](Problem - 246E - Codeforces)

思路

就是裸的(但不是神的)DSU on tree

但是主教练给了个思考方向:bfs序???很合理,深深感觉思路被局限了。

蒟蒻只会看题解,尽管这是一道简单题(我不会dsu)

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
#define pii pair<int,int>
vector<pii>q[maxn];//存储问题 
struct Node{
	string name;
	int fa,num;
}node[maxn];
struct Edge{
	int v,nxt;
}edge[maxn];
int head[maxn],edgetot;
void add(int u,int v){
//	cout<<"add "<<u<<' '<<v<<endl;
	edge[++edgetot]=(Edge){v,head[u]};
	head[u]=edgetot;
}
int dep[maxn],sz[maxn],son[maxn],ans[maxn];
void dfs1(int u,int fa){
	dep[u]=dep[fa]+1;
	if(!head[u])sz[u]=1;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		dfs1(v,u);
		if(sz[son[u]]<sz[v])son[u]=v;
		sz[u]+=sz[v];
	}
}
set<string>name[maxn*2];
int vis[maxn];
void del(int x){
	name[dep[x]].clear();
	for(int i=head[x];i;i=edge[i].nxt)del(edge[i].v);
}
void add(int x){
//	cout<<"add u fa"<<" "<<edge[head[x]].v<<endl;
	name[dep[x]].insert(node[x].name);
	for(int i=head[x];i;i=edge[i].nxt)add(edge[i].v);
//	cout<<"added u fa"<<" "<<x<<endl;
}
void dfs2(int u,int fa){//dsu 探究某深度的个数 
	vis[u]=1;
	for(int i=head[u];i;i=edge[i].nxt){//轻 
		int v=edge[i].v;
		if(v==son[u])continue;
		dfs2(v,u);
		del(v);
	}
	if(son[u])dfs2(son[u],u);//重
	for(int i=head[u];i;i=edge[i].nxt){
		if(edge[i].v!=son[u])add(edge[i].v);//重儿子之前操作了妹清空 
	}
	name[dep[u]].insert(node[u].name);//加进去后统计答案 
	for(auto i:q[u])ans[i.second]=name[i.first].size();
	//[dsu]意义在于不用清空son[u] 
}
int main(){
//	ios::sync_with_stdio(0),cin.tie(0);
	int n,m,k,v,r;
	cin>>n;
	string s;
	for(int i=1;i<=n;++i){
		cin>>s>>r;
		node[i]=(Node){s,r,i};
		add(r,i);
	}
	for(int i=1;i<=n;++i)if(!dep[i])dfs1(i,0);
	cin>>m;
	for(int i=1;i<=m;++i){
		cin>>v>>k;
		q[v].push_back({dep[v]+k,i});
	}
	for(int i=1;i<=n;++i)
		if(!vis[i])dfs2(i,0),del(i);
	for(int i=1;i<=m;++i)cout<<ans[i]<<"\n" ;
	return 0;
}

代码有点丑,不过好在代码不长

posted @ 2024-07-23 17:06  余亦宸  阅读(36)  评论(2)    收藏  举报