2020牛客暑期多校训练营(第五场) B Graph

这题可以说就是cf888g改编了一下,加上有人赛中发题解,所以过了一百多人,实际上还是很难的

 首先我们要先明确一个东西:这个图任意两个点u,v边权值始终不变,因为它所在的环异或和始终等于0,所以,边uv的值就是这个环其他边的异或和,现在即使它所在的环的某条边x被删去了,由于图要联通,那x肯定是被它所在的另一个环的其他边代替,而这些边的异或和等于x的值,这其实相当于没有删x,uv这条边还是在一个同样的环里,权值必然不会变

现在我们就可以将每个点的值变成根节点到他的路径异或和,uv连边,边值就是u点到v点路径异或和,现在可以将原图视为一个完全图,uv边值就是a[u]^a[v],我们最后还是要得到一颗树,所以我们就是求这个完全图的最小生成树

这其实就是cf888g,可以参考我的另一篇博客

 

#include
#include
#include
#include
#include
#include
#define ll long long
#include 
#include 
using namespace std;
#define maxn 3300000+5
ll tre[maxn][3],pos=0,sum[maxn];
struct node
{
    ll to,w;
};
vectore[105000];ll a[maxn];
void add(ll x)
{
    ll c=0;
    for(ll i=30;i>=0;i--)
    {
        ll y=(x>>i)&1ll;
        if(!tre[c][y]) tre[c][y]=++pos;
        c=tre[c][y];
        sum[c]++;
    }
}
ll Find(ll x,ll y,ll step)
{
    ll ans=1e18;
    if(step==-1) return 0;
    if(tre[x][0])
    {
        if(tre[y][0])//也就是说,尽量保证左右两边数每位尽量一致,这样一致异或就是0
        {
            ll w=Find(tre[x][0],tre[y][0],step-1);
            ans=w;
        }
        else
        {
            ll w=Find(tre[x][0],tre[y][1],step-1);
            ans=w+(1ll<0)//只有0和1都有才会分开连边
    {
        ans+=Find(tre[c][0],tre[c][1],step-1)+(1ll<

 

你可能感兴趣的:(1000篇,字典树,boruka)