beginend

只要在路上,就没有到不了的远方

bzoj 4551: [Tjoi2016&Heoi2016]树 并查集

题意:有一棵树,一开始根节点是黑色的,其余节点都是白色的。要求资瓷两个操作:

给某个节点变成黑色

查询离某个节点最近的祖先


分析:一开始往各种数据结构和神奇的算法上面去想但都没卵用,也想过离线,但感觉貌似不行就pass了。结果正解真的是离线搞……

以后有想法后一定要仔细想清楚是否能行。

正解其实就是从后往前搞然后用并查集维护一下就好了。

一次AC不解释


代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;

int n,m,f[N],fa[N],ans[N],x[N],last[N],cnt,tag[N];
char ch[N][2];
struct edge{int to,next;}e[N*2];

void insert(int u,int v)
{
	e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
	e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}

int find(int x)
{
	if (f[x]==x) return x;
	f[x]=find(f[x]);
	return f[x];
}

void dfs(int x,int p)
{
	if (x!=p) f[find(x)]=find(p);
	for (int i=last[x];i;i=e[i].next)
	{
		if (e[i].to==fa[x]) continue;
		fa[e[i].to]=x;
		if (tag[e[i].to]) dfs(e[i].to,e[i].to);
		else dfs(e[i].to,p);
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		insert(u,v);
	}
	tag[1]++;
	for (int i=1;i<=m;i++)
	{
		scanf("%s%d",&ch[i],&x[i]);
		if (ch[i][0]=='C') tag[x[i]]++;
	}
	for (int i=1;i<=n;i++)
		f[i]=i;
	dfs(1,1);
	for (int i=m;i>=1;i--)
		if (ch[i][0]=='C')
		{
			tag[x[i]]--;
			if (!tag[x[i]]) f[find(x[i])]=find(fa[x[i]]);
		}
		else ans[i]=find(x[i]);
	for (int i=1;i<=m;i++)
		if (ch[i][0]=='Q') printf("%d\n",ans[i]);
	return 0;
}


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33229466/article/details/52370576
个人分类: 并查集
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

bzoj 4551: [Tjoi2016&Heoi2016]树 并查集

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭