P10530 [XJTUPC2024] 生命游戏 题解

题目大意

一棵树一共 $ n $ 个点如果有 $ k $ 个点与某一个点相连那么这一轮的结尾这个点就会

思路

这道题有几个坑!

  1. 并没有说哪一个节点是根节点。

  2. 双向边记得开双倍数组。

  3. 等这一轮的点消除完了才能再次判断哪一些点可以消除。

首先我们创建一个数组 $ Size_{n} $ 来表示这个点与几个存活的点有连边,既然都说到存活了那么我们还需要创建一个数组 $ life_{n} $ 来表示这个点是否存活。我们还需要注意到一个东西就是消除完点后寻找一个点是否边数为 $ k $,必须是跟这些消除的点所相连的点不然一个点的边数为什么会平白无故的减少。还有最后一个要点再添加消除的点的时候我们要看当前点是否已经被消除过一次了(肯能会有两个消除的点连着同一个点在添加时我们也不好判断)。

最后答案跑一边 dfs 就行了。

如果你全部都懂了的话建议去写吧,代码量极其短我觉得因该是普及组第三题的难度

Code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#define sc(ppt) scanf("%d" , &ppt)
#define ll long long
#define prt printf
using namespace std; // 屎山头文件

const int maxn = 1e6 + 1;
bool life[maxn] , vis[maxn]; //life 表示这个点是否存活 vis dfs是表示这个点是否搜索过 
int n , k , Size[maxn] , ans = 0; //size 当前点与几个存活的点相连 
int h[maxn] , cnt = 0;
queue<int> q , p; //q需要消除的点 p被消除完的点判断下一部分该消除哪一些点 
struct edge{
	int next , to;
}e[maxn << 1]; //双边 

inline void add(int u , int v){
	++ cnt;
	e[cnt].next = h[u] ; e[cnt].to = v;
	h[u] = cnt;
} // 链式前向心 

void dfs_ans(int u , int fa){
	vis[u] = 1;
	for(int i=h[u] ; i ; i=e[i].next){
		int v = e[i].to;
		if(v == fa || vis[v] == 1 || life[v] == false) continue;
		dfs_ans(v , u);
	}
} // 树上搜索板子多了几个判断 

signed main(){
	sc(n) ; sc(k) ;
	for(int i=1 ; i<n ; i++){
		life[i] = life[i + 1] = true;
		int u , v ; sc(u) ; sc(v) ;
		add(u , v);
		add(v , u);
		Size[u] ++ ; Size[v] ++;
	} // 输入 
	for(int i=1 ; i<=n ; i++) if(Size[i] == k) q.push(i);
	while(! q.empty()){ // 判断是否还有可以消除的点 
		while(! q.empty()){ // 消除当前需要消除的点 
			int u = q.front() ; q.pop() ; p.push(u);
			if(life[u] == false) continue;
			for(int i=h[u] ; i ; i=e[i].next){
				int v = e[i].to;
				Size[v] --; // 与他有边的点Size-- 
			}
			life[u] = false; // 趋势了 
		}
		while(! p.empty()){ // 寻找下一些需要消除的点 
			int u = p.front() ; p.pop() ;
			for(int i=h[u] ; i ; i=e[i].next){
				int v = e[i].to;
				if(life[v] == true && Size[v] == k) q.push(v);
			}
		}
	}
	for(int i=1 ; i<=n ; i++){
		if(vis[i] == 0 && life[i] == true){ // 看有几个连通块 
			dfs_ans(i , -1);
			++ ans;
		}
	}
	prt("%d" , ans);
	return 0;
}
//CaoSheng' code
posted @ 2024-05-30 21:25  CaoSheng  阅读(36)  评论(0)    收藏  举报