zoukankan      html  css  js  c++  java
  • 【Codeforces 1338B】Edge Weight Assignment

    题目链接

    链接

    翻译

    让你构造一棵树,使得任意两个叶子节点之间路径的权重异或和为 (0)

    并且,树中用到的边的权重的不同值的个数设为 (f),让你求 (f) 的最大值和最小值。

    题解

    最小值不会超过 (3)

    可以转化为是在给每个点标记数字,然后边上的权重就是连接它们两个点上标的数字的异或值。

    这样的话,只要保证任意两个叶子节点上标记的数字是一样的,就能满足题意了。

    我们可以把所有的叶子都标记上 (1),然后中间的非叶子节点标记上 (2)(3) (因为权重要大于 (0),所以相邻两个节点权重不能相同)。

    可以想见,如果只用 (1)(2) 就能让树上相邻两个点数字不同(且叶子节点数字都相同),那么只会产生一种边权,最小答案就可以为 (1),否则 (3)

    个数字,两两异或最多组成 (3) 种权重。因此最小答案的最大值就为 (3)

    关于等于 (1) 的判断,可以选择一个叶子节点作为根进行 (dfs) 然后求出它到其他叶子节点的距离,如果满足这些到叶子节点的距离都为偶数。那么就可以

    (1),因为任意两个节点的树上距离为 (dis(x,root)+dis(y,root)-2*dis(lca(x,y),root))

    对于最大值的情况,显然只要让边权为 (2^0,2^1,2^2....) 然后和叶子节点连接的那个边权等于前面这些数字的和就好了,即二进制全为 (1)

    这样的话,理想情况下我们所有边的边权都可以不同。

    但是理想是丰满的,现实是残酷的。对于连在同一个节点上的两个叶子节点,它们俩和这个节点的边权必然是相同的,所以要减掉。

    直接给结论吧,最大值为 (n-1-cntLeaf+cntSpecial) 这里的 (cntSpecial) 是所有和叶子节点有连接的点的个数。

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    const int N = 1e5;
    
    int n;
    int du[N+10],dis[N+10];
    vector<int> g[N+10];
    
    //[6]写dfs
    void dfs(int x,int fa){
        for (int y:g[x]){
            if (y==fa){
                continue;
            }
        //[7]统计到这个点的距离
            dis[y] = dis[x] + 1;
            dfs(y,x);
        }
    }
    
    int main(){
        // freopen("C://1.cppSourceProgram//rush.txt","r",stdin);
        ios::sync_with_stdio(0),cin.tie(0);
        //step1 输入数据
        cin >> n;
        for (int i = 1;i <= n-1; i++){
    
            int x,y;
            cin >> x >> y;
            //step2 统计度信息
            du[x]++;du[y]++;
            // 5 简图
            g[x].push_back(y);
            g[y].push_back(x);
        }
        //step3 找个度为 1 的叶子当根
        int root = 1;
        for (int i = 2;i <= n; i++){
            if (du[i] == 1){
                root = i;
            }
        }
        //step4 从root 开始做 dfs
    
        dfs(root,-1);
    
        int mi = 1;
        //[8]看看是不是到所有叶子节点的距离都为偶数
        for (int i = 1;i <= n; i++){
            if (dis[i]%2!=0 && du[i] == 1){
                mi = 3;
            }
        }
        cout << mi <<" ";
        //[9] 找和叶子节点相邻的节点数目
        int cnt1 = 0;
        //[10] 叶子节点数
        int cntLeaf = 0;
        for (int i = 1;i <= n; i++){
            if (du[i] == 1){
                cntLeaf++;
            }
            int ok = 0;
            for(int y:g[i]){
                if (du[y] == 1){
                    ok=1;
                }
            }
            cnt1+=ok;
        }
        // [11] math
        int ma = n - 1 - cntLeaf + cnt1;
        cout << ma << endl;
        return 0;
    }
    
    
  • 相关阅读:
    MODIS系列之NDVI(MOD13Q1)三:.jdk文件配置+MRT安装
    MODIS系列之NDVI(MOD13Q1)二:modis数据相关信息
    MODIS系列之NDVI(MOD13Q1)一:数据下载(二)基于FTP
    MODIS系列之NDVI(MOD13Q1)一:数据下载(一)基于插件
    Python 1基础语法四(数字类型、输入输出汇总和命令行参数)
    Python 1基础语法三(变量和标识符的区别)
    mysql Can't connet MySQL server to '@localhost'
    使用get传参的时候,参数在后头获取不到或者出现别的错误。
    搭建nexus后,进入首页的时候出现warning: Could not connect to Nexus.错误
    在配置dubbo框架的时候出现dubbo:application标签无法识别问题。
  • 原文地址:https://www.cnblogs.com/AWCXV/p/14143405.html
Copyright © 2011-2022 走看看