noip 模拟 27 (牛半仙的妹子Tree)

正解虚树,树剖等等等等。。。。

玄解 LCA,模拟等等等等。。。。

这里讲讲考场打的模拟算法。

顾名思义,模拟就是模拟传染,针对这道题(random题)进行了很优的优化。
主题代码

inline void find() {
	queue<int>s;
	while(!q.empty()) {
		int x=q.front(); q.pop();
		for(re int i=head[x],to;i;i=edge[i].nxt) {
			to=edge[i].var;
			if(!v[to]) { s.push(to); sum.push(to); v[to]=1; }
		}
	}
	while(!s.empty()) { q.push(s.front()); s.pop(); }
}

然而引起了考场打正解大佬的不满,把链图,菊花图加进了数据,
然后LCA和模拟双双被卡。。

特判就该上了 能打暴力杜绝正解

#include <bits/stdc++.h>
#define re register
#define int long long
#define db double
#define pir make_pair
using namespace std; 
const int maxn=100010;
inline int read() {
    int s=0,w=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') w=-1;ch=getchar(); }
    while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
    return s*w;
}
queue<int>q,sum;
int n,m,du[maxn];
bool v[maxn],o;
int cnt,head[maxn];
struct EDGE { int var,nxt; } edge[maxn<<1];
inline void add(int a,int b) { edge[++cnt]=(EDGE){b,head[a]}; head[a]=cnt; }
inline void find() {
	queue<int>s;
	while(!q.empty()) {
		int x=q.front(); q.pop();
		if(du[x]==n-1) { o=1; continue; }
		for(re int i=head[x],to;i;i=edge[i].nxt) {
			to=edge[i].var;
			if(!v[to]) { s.push(to); sum.push(to); v[to]=1; }
		}
	}
	while(!s.empty()) { q.push(s.front()); s.pop(); }
}
signed main(void) {
	n=read(),m=read(); 
	for(re int i=1,u,e;i<n;i++) {
		u=read(),e=read();
		add(u,e); add(e,u); du[e]++,du[u]++;
	}
	for(re int i=1,k,x;i<=m;i++) {
		k=read(); x=read();
		if(k==1) {
		    find();
		    if(du[x]==n-1) o=1;
		    else if(!v[x]) { q.push(x); sum.push(x); v[x]=1; }
		}
		else if(k==2) {
			o=0;
			while(!sum.empty()) { v[sum.front()]=0; sum.pop(); } 
			while(!q.empty()) q.pop();
		}
		else if(k==3) {
			find(); 
			(v[x]||o)? printf("wrxcsd\n"):printf("orzFsYo\n");
		}
	}
}

当然,还是应该学习正解的。

posted @ 2021-08-06 08:44  zJx-Lm  阅读(35)  评论(0编辑  收藏  举报