zoukankan      html  css  js  c++  java
  • [并查集][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
    ",ans);
    62         }
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    怎样简单编写一个html网页
    C# 委托实现冒泡排序
    C# 运算符
    EF 多表联查方法
    Log4net 配置文件
    vs调试 iis发布之后的项目
    继承 ,构造方法使用
    C#扩展方法
    partial 部分类
    WeakReference 弱引用
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8568050.html
Copyright © 2011-2022 走看看