51nod_1809 黑白图(DFS+树状数组)

黑白图

Problem Description

黑白图是一个由n个点和n-1条边组成的无向连通图。在图中最多只有一个节点的度会超过2,其余点的度要么为1,要么为2。一个节点的度指的是与该节点有边相连的节点的个数。图中的边是有颜色的,要么白色,要么黑色。一开始所有的边都是黑色。

对黑白图我们可以进行以下三种操作:

1)把第i条边变成黑色。第i条边是指在图中编号为i的边。(这里保证第i条边在变色前是白色的)

2)把第i条边变成白色。(这里保证第i条边在变色前是黑色的)

3)找出从点a到点b的最短路,并且在这条路上只有黑边。或者判断出a和b点之间不存在由黑边组成的路。

节点编号从1到n,边的编号从1到n-1。

样例解释:

在样例一中,1号点和2号点由1号边连接。2号点和3号点由2号边连接。在边被着色前,所有的点都是相互连通的。所以从1号点到3号点最短路是2。

如果我们把2号边变成白色,则3号点与其它点将不再连通。

Input

单组测试数据
第一行,有一个整数n(2≤n≤10^5) 表示图中点的个数。
接下来的n-1行表示边的信息。
每行用vi ui(1≤vi,ui≤n,vi≠ui)表示第i条边连接的两个点。
这里保证图一定是黑白图,并且没有自环和重边。

接下来一行,有一个整数m(1≤m≤3*10^5),表示对图进行操作的次数。
接下来有m行,每行用以下形式表示。
首先有一个整数type(1≤type≤3),表示操作的类型。

如果type=1,则表示要把某条变成黑色。这种情况下,后面会跟一个整数id(1≤id≤n-1),表示要变色的边的编号。

如果type=2,则表示要把某条变成白色。这种情况下,后面会跟一个整数id(1≤id≤n-1),表示要变色的边的编号。

如果type=3,则表示要查询两个点之间由黑边组成的最短距离。这种情况下,后面会跟两个整数a,b(1≤a,b≤n,a有可能等于b),表示要查询的两个节点的编号。
具体可参考测试用例。

每行输入中的整数都由一个空格隔开。
边按输入的顺序进行编号。

Output

对于每个type=3的操作,输出a到b的最短距离。
如果不存在从a到b由黑边组成的路径,则输出“-1”(没有引号)。
输出的相对顺序和输入的相对顺序相同。
每个操作输出占一行。

Sample Input

样例一
3
1 2
2 3
7
3 1 2
3 1 3
3 2 3
2 2
3 1 2
3 1 3
3 2 3
样例二
6
1 5
6 4
2 3
3 5
5 6
6
3 3 4
2 5
3 2 6
3 1 2
2 3
3 3 1

Sample Output

输出一
1
2
1
1
-1
-1
输出二
3
-1
3
2

题解:

一棵树,最多只有一个节点的度数超过2。显然将这个点(没有度数超过2的就随便选一个)作为根,这个点下面的每个子树都是链状。DFS将每个点重新编号,保证同一子树内编号连续,同时处理出每个点到根的距离。
利用树状数组维护一段连续编号内的黑点的数量,因为维护的是边的信息,而重新编号的是点,所以将一条边的两点中编号较大的那个点代表这条边,更新都对该点操作即可。如果LCA(u,v)是根,将其作为两条链即可。利用子树编号连续来判断链内黑边的数量即可。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-7
 
using namespace std;
typedef long long LL;   
typedef pair<int, int> P;
const int maxn = 200100;
const int mod = 998244353;
int cnt, in[maxn], id[maxn], dis[maxn], rot[maxn], p[maxn];
int u[maxn], v[maxn];
vector<int> g[maxn];
int lowbit(int x);
int query(int x);
void Update(int x, int y, int n);
void dfs(int u, int rt, int fa, int d);

int main()
{
    int n, m, i, j, k, op, be = -1;
    cnt = 2;
    scanf("%d", &n);
    for(i=2;i<=n;i++)Update(i, 1, n);
    for(i=1;i<n;i++){
        scanf("%d %d", &u[i], &v[i]);
        in[u[i]]++, in[v[i]]++;
        if(in[u[i]]>2)be = u[i];
        if(in[v[i]]>2)be = v[i];
        g[u[i]].push_back(v[i]);
        g[v[i]].push_back(u[i]);
    }
    if(be == -1)be = 1;
    id[be] = 1, rot[be]=2;
    for(i=0;i<g[be].size();i++)
        dfs(g[be][i], cnt, be, 1);
    scanf("%d", &m);
    while(m--)
    {
        scanf("%d", &op);
        if(op == 1){
            scanf("%d", &i);
            j = max(id[u[i]], id[v[i]]);
            Update(j, -1, n);
        }else if(op ==2){
            scanf("%d", &i);
            j = max(id[u[i]], id[v[i]]);
            Update(j, 1, n);
        }else{
            int l, r;
            scanf("%d %d", &l, &r);
            if(rot[l] == rot[r]){
                if(id[l]>id[r])swap(l,r);
                if(id[r]-id[l] == query(id[r])-query(id[l]))
                    printf("%d\n", dis[r]-dis[l]);
                else printf("-1\n");
            }else
            {
                if(id[r]-rot[r]+1+id[l]-rot[l]+1 == query(id[r])-query(rot[r]-1)+query(id[l])-query(rot[l]-1))
                    printf("%d\n", dis[r]+dis[l]);
                else printf("-1\n");
            }
            
        }
    }
    return 0;
}

int lowbit(int x)
{
    return x&(-x);
}

void Update(int x, int y, int n)
{
    for(int i=x;i<=n;i+=lowbit(i))
        p[i] += y;
}

int query(int x)
{
    int sum = 0;
    for(int i=x;i>0;i-=lowbit(i))
        sum += p[i];
    return sum;
}

void dfs(int u, int rt, int fa, int d)
{
    id[u] = cnt++;
    rot[u] = rt;
    dis[u] = d;
    for(int i=0;i<g[u].size();i++)
        if(g[u][i] != fa){
            dfs(g[u][i], rt, u, d+1);
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值