牛客网Portal

题目描述:

Mr. W got a new graph with N vertices and N - 1 edges. It's a connected graph without cycles. Each edge should have an ugly value. To make the graph more beautiful, Mr. W hope you can help him modify it. You can delete or add one edge with an ugly value at a time and you can do it as many times as you want. But the following conditions should be satisfied at any time:
1. The graph is connected.
2. For each cycles in the graph, the XOR sum of all ugly values in the cycle is 0.
Mr. W wants to know the minimum sum of ugly values of all edges in the graph.

输入描述:

 

输出描述:

 

示例:

输入
6
0 1 1
1 2 4
1 3 3
0 4 5
0 5 2

  

输出
7

做法:我们脑袋一拍,可以发现任意两个点之间连边的权值都是固定的。

由于可以得出:图始终联通,所以两点间始终存在至少一条路径,如果存在多条,那么根据:

  • 环的异或和为0;
  • 两点间的路径的异或和应该相等,且始终是固定的。

所以可以给每个点一个权值,那么两点间的连边权值就应该是两端点权的异或。

接下来的问题就是异或最小生成树。

字典树 就TM烦。

接下来便是参考代码:

#include<bits/stdc++.h>
using namespace std;
int n,tot,cnt;
int head[100005],dp[100005],tree[30000010][2];
long long ans;
struct node
{
    int v;
    int w;
    int next;
}a[100005<<1];
void dfs(int x,int h)
{
    for (int i=head[x]; i!=-1; i=a[i].next)
    {
        int v=a[i].v;
        if(v==h) continue;
        dp[v]=dp[x]^a[i].w;
        dfs(v,x);
    }
}
void insert(int x)
{
    int p=0;
    for (int i=29; i>=0; i--)
    {
        int now=x>>i&1;
        if(!tree[p][now])
        {
            cnt++;
            tree[p][now]=cnt;
            tree[cnt][0]=0;
            tree[cnt][1]=0;
        }
        p=tree[p][now];
    }
}
int ask(int x)
{
    int p=0,ans=0;
    for (int i=29; i>=0; i--)
    {
        int now=x>>i&1;
        if(!tree[p][now]) now^=1;
        p=tree[p][now];
        if(now) ans+=1<<i;
    }
    return ans;
}
void bfs(int x, int l, int r)
{
    if(x<0)
        return ;
    int mid=l-1;
    for (int i=l; i<=r; i++) 
        if(!(1<<x&dp[i])) mid=i;
    if(l<=mid) bfs(x-1,l,mid);
    if(mid<r) bfs(x-1,mid+1,r);
    if(mid<l || mid>=r) return ;
    cnt=0;
    tree[0][0]=0;
    tree[0][1]=0;
    for (int i=l; i<=mid; i++)
        insert(dp[i]);
    int minn=0x3f3f3f3f;
    for (int i=mid+1; i<=r; i++) minn=min(minn,dp[i]^ask(dp[i]));
    ans+=minn;
}
 
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    int x,y,z;
    for (int i=1,u,v,w; i<n; i++){
        scanf("%d%d%d",&x,&y,&z);
        x++,y++;
        a[tot].v=y;
        a[tot].w=z;
        a[tot].next=head[x];
        head[x]=tot++;
        a[tot].v=x;
        a[tot].w=z;
        a[tot].next=head[y];
        head[y]=tot++;
    }
    dfs(1,0);
    sort(dp+1,dp+1+n);
    bfs(29,1,n);
    printf("%lld\n", ans);
    return 0;
}//码农教程请不要爬我代码
View Code

猜你喜欢

转载自www.cnblogs.com/WWWZZZQQQ/p/13380560.html
今日推荐