Codeforces 1339 D. Edge Weight Assignment (Construction)

Link to the
topic The main idea:
Given a tree, give each edge a positive weight and then make the sum of the XOR on the path between any two leaves to zero. The maximum value and minimum value of the weight type of the output side.

Problem-solving ideas:
minimum value:
only 1, 3 answers. If the distance between the two leaves is an odd number, both can be converted to 3 for processing. At this time, there must be three values, because if it is two or one value, the same value XOR will leave a value. If the length is even, only one kind is needed.
For distance, just select a leaf as the root node, and then use dfs to find the depth. Because the distance between the two leaves to the root is different in parity, the distance between them is odd, and if the parity to the root is the same, the parity between the two leaves is the same.
Maximum value: It
can be seen that if each edge weight is 2 x 2^x not the same, then the two sides will never XOR the value of the other side. So at this time, the weight of each edge is 2 x 2^x is enough, there are n-1 edges, but if a node has multiple direct son leaf nodes, then these edge weights must be equal, because the length is only 2, they must be the same. So the current node is the number of direct sons and leaves-1.
For each leaf and the parent node, the edge weight is set to the XOR sum of the path from the root to his father, so that the XOR sum of the path between any two leaf nodes is 0. (You can draw a picture to understand)

Problem-solving code

#include<bits/stdc++.h>
using namespace std;
mt19937 rng_32(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
const int maxn=2e5+10;
struct E{
    int to,nxt;
}e[maxn];
int sonsz[maxn];
int head[maxn],tot;
void adde(int u,int v)
{
    e[++tot]=E{v,head[u]};
    head[u]=tot;
}
int d[maxn];
bool odd;
void dfs(int u,int fa,int dep)
{
    int c=0;
    for (int i=head[u];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if (to==fa)
        continue;
        c++;
        dfs(to,u,dep+1);
    }
    //奇偶性标记
    if (c==0 && (dep&1))
        odd=1;
}
int main()
{
    int n,t1,t2;
    int lea=0;
    cin>>n;
    for (int i=1;i<n;i++)
    {
        cin>>t1>>t2;
        d[t1]++;
        d[t2]++;
        adde(t1,t2);
        adde(t2,t1);
    }
    int top=1;
    ll ans=n-1;
    for (int i=1;i<=n;i++)
    {
        if (d[i]==1)
        {
            top=i;
            lea++;
            //给直接父亲的儿子叶子+1
            sonsz[e[head[i]].to]++;
            //如果不止一个 就要减掉
            if (sonsz[e[head[i]].to]!=1)
            ans--;
        }
    }
    dfs(top,top,0);
    if (odd)
        cout<<3<<" ";
    else
        cout<<1<<" ";
    cout<<ans;   
    return 0;
}
Published 12 original articles · Like1 · Visits 327

Guess you like

Origin blog.csdn.net/qq_41818939/article/details/105490521