晚间测试9 B. 主仆见证了 Hobo 的离别 神奇建树
题目描述
分析
考虑离线处理之后建树
如果 \(a_1,a_2,...,a_k\) 的交是 \(b\)
那我们从 \(b\) 到 \(a_1,a_2,...,a_k\) 建一条边权为 \(0\) 的边
同样地,如果 \(a_1,a_2,...,a_k\) 的并是 \(b\)
那我们从 \(b\) 到 \(a_1,a_2,...,a_k\) 建一条边权为 \(1\) 的边
\(k=1\) 既是交又是并,要特殊处理一下,可以建边权为 \(2\) 的边
询问时,我们通过 \(dfn\) 序判断两个节点是否有父子关系
如果没有,直接输出 \(0\)
否则如果 \(x\) 是 \(y\) 的祖先,当\(x\) 到 \(y\) 的路径中边权只为 \(0\) 或 \(2\) 时输出 \(1\)
如果 \(y\) 是 \(x\) 的祖先,当\(x\) 到 \(y\) 的路径中边权只为 \(1\) 或 \(2\) 时输出 \(1\)
其它情况输出 \(0\)
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e6+5;
int n,m,now,h[maxn],tot=1;
struct asd{
int to,nxt,val;
}b[maxn<<1];
void ad(int aa,int bb,int cc){
b[tot].to=bb;
b[tot].nxt=h[aa];
b[tot].val=cc;
h[aa]=tot++;
}
int dfn[maxn],siz[maxn],dfnc,dep[maxn],dis[maxn],du[maxn],haha[maxn];
void dfs(int now,int fa){
dfn[now]=++dfnc;
siz[now]=1;
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(u==fa) continue;
haha[u]=haha[now];
if(b[i].val==2) haha[u]++;
dep[u]=dep[now]+b[i].val;
dis[u]=dis[now]+1;
dfs(u,now);
siz[now]+=siz[u];
}
}
int pd(int aa,int bb){
if(dfn[aa]>dfn[bb] && dfn[aa]<=dfn[bb]+siz[bb]-1) return bb;
if(dfn[bb]>dfn[aa] && dfn[bb]<=dfn[aa]+siz[aa]-1) return aa;
return 0;
}
int x[maxn],y[maxn],cnt;
int main(){
memset(h,-1,sizeof(h));
n=read(),m=read();
now=n;
rg int aa,bb,cc,dd;
for(rg int i=1;i<=m;i++){
aa=read(),bb=read(),cc=read();
if(aa==0){
now++;
if(cc==1){
dd=read();
ad(dd,now,2);
ad(now,dd,2);
du[dd]++;
} else if(bb==0){
for(rg int j=1;j<=cc;j++){
dd=read();
ad(now,dd,0);
du[dd]++;
}
} else {
for(rg int j=1;j<=cc;j++){
dd=read();
ad(now,dd,1);
du[dd]++;
}
}
} else {
x[++cnt]=bb;
y[cnt]=cc;
}
}
for(rg int i=1;i<=now;i++){
if(du[i]==0){
dfs(i,0);
}
}
for(rg int i=1;i<=cnt;i++){
rg int now=pd(x[i],y[i]);
if(x[i]==y[i]) printf("1\n");
else if(now==0) printf("0\n");
else if(now==x[i]){
if(dep[x[i]]-dep[y[i]]==(haha[x[i]]-haha[y[i]])*2) printf("1\n");
else printf("0\n");
} else {
if(dep[y[i]]-dep[x[i]]==dis[y[i]]-dis[x[i]]+haha[y[i]]-haha[x[i]]) printf("1\n");
else printf("0\n");
}
}
return 0;
}