[并查集][bfs]JZOJ P3973 黑白数

Description

给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:
1. 查询 u 到根路径上的第一条黑色边的标号。
2. 将 u 到 v 路径上的所有边的颜色设为黑色。
 

Input

第一行两个数 n, m 分别表示点数和操作数。
接下来 n − 1 行,每行 2 个数 u, v 表示一条 u 到 v 的边。
接下来 m 行,每行为以下格式:
• 1 v 表示第一个操作
• 2 v u 表示第二种操作

Output

对于每个询问,输出相应答案。如果不存在,输出 0 。
 

Sample Input

5 4
1 2
1 3
2 4
2 5
1 2
2 2 3
1 3
1 4

Sample Output

0
2
1
 

Data Constraint

对于 30% 的数据:n, m ≤ 10 3
对于 100% 的数据:n, m ≤ 10 6
 

Hint

注意:根是1

题解

  • 首先,我们先将边打进队列里
  • 那么,就可以一波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 }

 

posted @ 2018-03-14 15:43  BEYang_Z  阅读(273)  评论(0编辑  收藏  举报