upc 5220: A Possible Tree(带权并查集。2017ICPC乌鲁木齐)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winter2121/article/details/81914112

5220: A Possible Tree

时间限制: 2 Sec  内存限制: 128 MB
提交: 41  解决: 11
[提交] [状态] [讨论版] [命题人:admin]

题目描述

Alice knows that Bob has a secret tree (in terms of graph theory) with n nodes with n − 1 weighted edges with integer values in [0, 260 −1]. She knows its structure but does not know the specific information about edge weights.
Thanks to the awakening of Bob’s conscience, Alice gets m conclusions related to his tree. Each conclusion provides three integers u, v and val saying that the exclusive OR (XOR) sum of edge weights in the unique shortest path between u and v is equal to val.
Some conclusions provided might be wrong and Alice wants to find the maximum number W such that the first W given conclusions are compatible. That is say that at least one allocation of edge weights satisfies the first W conclusions all together but no way satisfies all the first W + 1 conclusions (or there are only W conclusions provided in total).
Help Alice find the exact value of W.

输入

The input has several test cases and the first line contains an integer t (1 ≤ t ≤ 30) which is the number of test cases.
For each case, the first line contains two integers n (1 ≤ n ≤ 100000) and c (1 ≤ c ≤ 100000) which are the number of nodes in the tree and the number of conclusions provided. Each of the following n−1 lines contains two integers u and v (1 ≤ u, v ≤ n) indicating an edge in the tree between the u-th node and the v-th node. Each of the following c lines provides a conclusion with three integers u, v and val where 1 ≤ u, v ≤ n and val ∈ [0, 260 − 1].

输出

For each test case, output the integer W in a single line.

样例输入

2
7 5
1 2
2 3
3 4
4 5
5 6
6 7
1 3 1
3 5 0
5 7 1
1 7 1
2 3 2
7 5
1 2
1 3
1 4
3 5
3 6
3 7
2 6 6
4 7 7
6 7 3
5 4 5
2 5 6

样例输出

3
4

【带权并查集】新鲜玩意。

并查集的基础上多一个数组,比如可以用sum[]多维护一个权值。

朴素的并查集模型,对于每个连通块有一个“队长”,那么就用sum[x]表示从x点到x的队长点之间的权值(比如本题就是维护异或和)。

在更新并查集时同时更新sum数组即可。

意义:对于仅确定区间权值和而不确定具体每个权值时,带权并查集是理想的选择。

【题意】

给出一棵树,然后又m条信息:  x  y  val 表示x到y之间的异或和为val。m条信息可能存在冲突。

问最多前几条信息是不冲突的。

【分析】

对本题来说,给个树没什么jb用,无非就是想说每两点之间的路径是唯一的。我们并不关心树的形状。

带权并查集处理信息,并用sum数组维护每个点x到其本连通块队长之间的路径异或和。

当某一条信息中两点x与y在统一连通块上,那么就必须满足  “x->队长”  ^  “y->队长”  ==  val,否则就有了冲突。

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX=2e5+5;
int fa[MAX];
ll sum[MAX];

int father(int x)
{
    if(x==fa[x])return x;
    int fx=fa[x];
    fa[x]=father(fa[x]);
    sum[x]^=sum[fx]; //由于x更换了队长,换的路径要算上
    return fa[x];
}
bool join(int x,int y,ll val)
{
    int fx=father(x);
    int fy=father(y);
    if(fx==fy)return false;
    sum[fx]^=sum[x]^sum[y]^val; //由于是异或,疑惑一下就抵消了
    fa[fx]=fy;
    return true;
}
int main()
{
    int T,n,m,x,y;
    ll val;
    cin>>T;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n-1;i++)scanf("%*d%*d");
        for(int i=1;i<=n;i++)fa[i]=i,sum[i]=0;
        int ans=m;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lld",&x,&y,&val);
            if(ans==m&&!join(x,y,val)&&(sum[x]^sum[y])!=val)
            {
                ans=i-1;
            }
        }
        printf("%d\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/winter2121/article/details/81914112
UPC
今日推荐