[并查集][bfs]JZOJ P3973 黑白数
题解
- 首先,我们先将边打进队列里
- 那么,就可以一波bfs,做并查集,求出深度,位于哪条边
- 然后,就比较暴力了
- 读入,如果为"1",那就一直往上跑,找到第一条出现的黑边
- 如果为"2",现将路径一直往上条,沿路都为黑边
代码
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int n,m,x,y,z,tot,head,tail,ans,w[2000001],state[2000001],visit[2000001],deep[2000001],k[2000001],next[2000001],v[2000001],to[2000001],last[2000001],fa[2000001]; 5 void insert(int x,int y,int z) 6 { 7 next[++tot]=y; 8 v[tot]=z; 9 to[tot]=last[x]; 10 last[x]=tot; 11 } 12 int main() 13 { 14 scanf("%d%d",&n,&m); 15 for (int i=1;i<=n-1;i++) 16 { 17 scanf("%d%d",&x,&y); 18 insert(x,y,i); insert(y,x,i); 19 } 20 head=0; tail=1; state[1]=1; visit[1]=1; deep[1]=1; 21 while (head<tail) 22 { 23 head++; x=state[head]; 24 for (int i=last[x];i;i=to[i]) 25 { 26 y=next[i]; 27 if (visit[y]==0) 28 { 29 fa[y]=x; 30 deep[y]=deep[x]+1; 31 k[y]=v[i]; 32 visit[y]=1; 33 tail++; 34 state[tail]=y; 35 } 36 } 37 } 38 for (int i=1;i<=m;i++) 39 { 40 scanf("%d%d",&x,&y); 41 if (x==2) 42 { 43 scanf("%d",&z); 44 if (deep[y]<deep[z]) swap(z,y); 45 while (deep[y]>deep[z]) w[y]=1,y=fa[y]; 46 while (y!=z) 47 { 48 w[y]=w[z]=1; 49 y=fa[y]; 50 z=fa[z]; 51 } 52 } 53 else 54 { 55 ans=0; 56 while (y!=0) 57 { 58 if (w[y]==1) { ans=k[y]; break; } 59 y=fa[y]; 60 } 61 printf("%d\n",ans); 62 } 63 } 64 return 0; 65 }