2021牛客暑期多校训练营7xay loves trees(dfs序,维护根出发的链)

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营7xay loves trees(dfs序,维护根出发的链)相关的知识,希望对你有一定的参考价值。

F xay loves trees

题意:

  • 给出两棵树,由这两棵树根据规则可以生成一个图,规则如下:如果u , v在第一棵树中满足其中一个点是另一个点祖先且最终所有所选的点都互相联通,在第二棵树中满足两个点都不是另外一个点的祖先,则u, v之间连一条边。
  • 求最后生成的图中最大的团。(团为子图中的完全图)

思路:

  • 原题来源,Codeforces Round #722 (Div. 1) C. Trees of Tranquillity,在树1加了一个联通的条件,改了好久都没改出来。
  • 首先观察到一个比较重要的性质:选出来的点在第一棵树上构成一条链(且不能中断),所以我们在第一颗树上需要dfs。
  • 再考虑到再第二棵树中 u,v 不存在祖先−子代关系。判断祖先和子代有无被选点可以用 dfs 序完成,我们先在第二棵树上求出每个点的dfs序,那么每个点的dfs序可以用一个区间表示[ in[u], out[u] ]表示, 一个点如果不在另一个点的子树内,那么他们的dfs序一定不相交,反之则一定包含。
  • 对于第一棵树,我们可以遍历第一棵树的每条链,用链表last和nxt[]维护当前链条,每次将链中每个点的dfs序放入set中按照区间左端点从小到大排序,当访问到新的节点的时候,如果当前节点与之前的链中的节点有冲突,那么就不断去掉链条顶部的点直到不冲突为止,然后加入当前节点继续遍历。去掉节点的时候开临时数组记录,回溯的时候加回去即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e5+1010;
vector<int>G1[maxn], G2[maxn];

int tim, in[maxn], out[maxn], rev[maxn];
void pre(int x, int fa){   //跑dfs序
	in[x] = ++tim;  rev[tim]=x;
	for(int to: G2[x]){
		if(to!=fa)pre(to,x);
	}
	out[x] = tim;
}

int ans, last, nxt[maxn];//开链表维护当前链
set<int>se;
void dfs(int x, int fa){
	int tmplast = last;  vector<int>tmp;
	while(se.size()){//如果u和链里有节点冲突,那就不断去掉链顶节点
		int ok =1;
		auto it=se.lower_bound(in[x]);
		if(it!=se.end() && *it<=out[x])ok=0; //相交
		else if(it!=se.begin()){
			it--;
			if(*it<=in[x]&&in[x]<=out[rev[*it]])ok=0;//x在it子树内
		}
		if(ok)break;
		se.erase(in[last]);
		tmp.push_back(in[last]);//回溯的时候需要加回去
		last = nxt[last];  //不断去掉链顶节点
	}
	se.insert(in[x]);//加入当前节点
	ans = max(ans, (int)se.size());
	for(int to : G1[x]){
		if(to!=fa){
			nxt[x] = to;
			dfs(to, x);
		}
	}
	se.erase(in[x]);  //回溯删除并复原
	for(int y : tmp)se.insert(y);
	last = tmplast;
}

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T;  cin>>T;
	while(T--){
		int n;  cin>>n;
		for(int i=1; i<=n; i++)G1[i].clear(),G2[i].clear();
		for(int i = 1; i < n; i++){
			int x, y;  cin>>x>>y;
			G1[x].push_back(y);
			G1[y].push_back(x);
		}
		for(int i = 1; i < n; i++){
			int x, y;  cin>>x>>y;
			G2[x].push_back(y);
			G2[y].push_back(x);
		}
		tim = 0;  pre(1,0);
		ans = 0;  last = 1;  se.clear();  dfs(1,0);
		cout<<ans<<"\\n";
	}
	return 0;
}

以上是关于2021牛客暑期多校训练营7xay loves trees(dfs序,维护根出发的链)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营7 F.xay loves trees(主席树+树上尺取)

2021牛客暑期多校训练营7 J. xay loves Floyd 预处理最短路+bitset

2021牛客暑期多校训练营2

2021牛客暑期多校训练营4

2021牛客暑期多校训练营9

2021牛客暑期多校训练营3