Codeforces Round 875 (Div. 2) C. Copil Copac Draws Trees

bfs解法

如果是暴力求解的话就每次都扫描一次所有边直到所有点都和树连接

优化:每次扫描我们可以发现会重复扫描那些已经存在树中的边了,因此我们可以只扫描还没有存在树中的边且是没扫过的边

对于每次更新,比如由点a已经在树中,更新点b,我们只需判断点a被更新到树中点的编号和a-b边的编号的大小,如果比它小的话则不变,否则加一

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <set>
#include <utility>
#include <vector>
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=2e5+10;
int t,n;
vector<PII> e[N];//记录下每个点所有相连的点以及边的编号大小 
queue<int> q;
int  fast[N],res[N];//fast记录每个点第一次被更新是由哪条边更新来的,并且记录下点的编号,res记录每个点需要几次更新 
bool st[N];
void solve(){
	cin>>n;
	memset(st,0,sizeof st);
	memset(fast,0,sizeof fast);
	for(int i=1;i<=n;i++) res[i]=1;
	for(int i=1;i<n;i++){
		int a,b;
		cin>>a>>b;
		e[a].push_back({b,i});
		e[b].push_back({a,i});
	}
	q.push(1);
	st[1]=1;
	while(q.size()){
		int k=q.front();
		q.pop();
		for(int i=0;i<e[k].size();i++){
			int x=e[k][i].x,y=e[k][i].y;
			if(st[x]) continue;//如果该点已经在树中了则停止 
			if(y>=fast[k]){
				res[x]=res[k];//如果该边的编号比更新k点的边的编号大则不变 
			}
			else res[x]=res[k]+1;//否则加一 
			fast[x]=y;
			q.push(x);
			st[x]=1;
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){//求最大值 
		ans=max(ans,res[i]);
	}
	cout<<ans<<endl;
	for(int i=1;i<=n;i++) e[i].clear();
}
int main(){
	cin>>t;
	while(t--){
		solve();
	}
}

 

posted @ 2023-06-24 21:26  突破铁皮  阅读(65)  评论(0编辑  收藏  举报