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");
}
}
}
当然,还是应该学习正解的。