Codeforces 1339D-Edge Weight Assignment (Data Structure-Tree)

Description

Ideas

I always have some ideas about this question, but I just can't write it. It took a long time to read the solution to understand. (The following pictures are from the cf solution )

Each node whose degree is greater than 2 is the LCA of some leaf nodes. Let this node be C in the figure. The dotted line represents the path from the leaf node to C, and all the edges above the path are merged into one edge. The weight of the merged edges is the XOR of the weights of the edges on the path.
figure 1

After such processing of the tree, a point is either a leaf node or an LCA point (set to point C). If it is point C, then it is either connected to the leaf node or another point C.
According to the intent of the question, xor (path (leaf1, C)) == xor (path (leaf2, C)) == xor (path (root, C))
Since point C may connect multiple leaf nodes, obviously all paths The weights of (leaf, C) are all equal, so these leaf nodes are combined into one (that is, leaf1 and leaf2 can be combined into one node).

In this way, any tree can be transformed into the form of the following figures.
Discuss by situation

  1. For the smallest f, you can always use no more than 3 digits. If the distance between each pair of leaf points is even (that is, the parity of all leaf points is even), then the minimum f is 1, otherwise it is 3.
    figure 2

  2. For the largest f, see figure and cf problem solution is easy to know the establishment. The maximum f is the number of all sides minus (the number of leaf points connected by each C point (before unmerging)-1)
    image 3

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N = 1e5 + 10;
 
vector<int> np[N];
int cnt[N];
int p[N];
 
void dfs(int u, int fa, int par) {
    p[u] = par;
    for(auto v : np[u]) {
        if(v == fa) continue;
        dfs(v, u, par ^ 1);
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    for(int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        np[u].push_back(v);
        np[v].push_back(u);
        cnt[u]++;
        cnt[v]++;
    }
    
    int mn = 1, mx = n - 1;
    for(int i = 1; i <= n; i++) {
        if(cnt[i] == 1) {
            dfs(i, -1, 0);
            break;
        }
    }
    
    for(int i = 1; i <= n; i++) {
        if(cnt[i] == 1 && p[i] == 1) {
            mn = 3;
            break;
        } 
    }
    
    for(int i = 1; i <= n; i++) {
        int ch = 0;
        for(auto v : np[i]) {
            if(cnt[v] == 1) {
                ch++;
            }
        }  
        if(ch != 0)
            mx -= (ch - 1);
    }
    
    cout << mn << " " << mx << endl;
}

Guess you like

Origin www.cnblogs.com/limil/p/12690898.html