社区讨论

WA15点求条

AT_abc302_h [ABC302Ex] Ball Collector参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@m5xvdker
此快照首次捕获于
2025/01/15 20:20
去年
此快照最后确认于
2025/11/04 11:33
4 个月前
查看原帖
CPP
/*
对于一个路径的答案即映射的图的包含点数减去连通块数量加上每一块是否存在一个强连通分量
包含点数很好维护
连通块数量也很好做
每一条边要么合并两个连通块、要么构成一个强连通分量、要么新加进一个点 
*/
#include<bits/stdc++.h>
#define int long long 
#define Maxn 200005 
using namespace std;
int a[Maxn],b[Maxn];
vector<int> q[Maxn];
int answer[Maxn],sz[Maxn];//每个询问的答案、每个点被访问的次数
//按秩合并并查集方便维护每个连通块的连通分量个数 
struct node {
	int sz,val,fa,lst; 
} f[Maxn];
stack<pair<int,node> > S; 
int find(int x) {
	if(f[x].fa == x)return x;
	return f[x].fa;
}
int cnt_lian,cnt_dian,res_lian;
void add(int x,int y) {
	S.push({x,f[x]});
	S.push({y,f[y]});
	if(f[x].sz > f[y].sz)swap(x,y);
	f[x].fa = y;
	f[y].sz += f[x].sz;
}
void erase() {
	f[S.top().first] = S.top().second;S.pop();
	f[S.top().first] = S.top().second;S.pop();
}
bool Insert(int x) {
	if(!sz[a[x]])res_lian ++,cnt_dian ++;sz[a[x]] ++; 
	if(!sz[b[x]])res_lian ++,cnt_dian ++;sz[b[x]] ++;
	int fu = find(a[x]),fv = find(b[x]);
	if(fu == fv) {
		if(!f[fu].val) {
			cnt_lian ++;
		} f[fu].val ++;
		return false;
	} else {
		add(fu,fv);
		res_lian --;
		return true;
	}
}
void Delete(int x,bool op) {
	if(!sz[a[x]])res_lian --,cnt_dian --;sz[a[x]] --; 
	if(!sz[b[x]])res_lian --,cnt_dian --;sz[b[x]] --;
	int fu = find(a[x]),fv = find(b[x]);
	if(!op) {
		f[fu].val --;
		if(!f[fu].val) {
			cnt_lian --;
		} 
	} else {
		erase();
		res_lian ++;
	}
}
void dfs(int x,int fa) {
	bool op = Insert(x);
//	cout<<x<<" ] "<<cnt_dian<<" "<<res_lian<<" "<<cnt_lian<<"\n";
	answer[x] = cnt_dian-res_lian+cnt_lian;
	for(int u:q[x]) {
		if(u == fa)continue;
		dfs(u,x);
	} Delete(x,op);
}
signed main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i]>>b[i],
		f[i] = {1,0,i,0};
	for(int i=1;i<n;i++) {
		int x,y;
		cin>>x>>y;
		q[x].push_back(y);
		q[y].push_back(x);
	} dfs(1,0);
	for(int i=2;i<=n;i++)cout<<answer[i]<<" ";
	return 0;
 }

回复

2 条回复,欢迎继续交流。

正在加载回复...