zoukankan      html  css  js  c++  java
  • P3698 [CQOI2017]小Q的棋盘

    $ color{#0066ff}{ 题目描述 }$

    小 Q 正在设计一种棋类游戏。

    在小 Q 设计的游戏中,棋子可以放在棋盘上的格点中。某些格点之间有连线,棋子只能在有连线的格点之间移动。整个棋盘上共有 V 个格点,编号为0,1,2 … , V− 1,它们是连通的,也就是说棋子从任意格点出发,总能到达所有的格点。小 Q 在设计棋盘时,还保证棋子从一个格点移动到另外任一格点的路径是唯一的。

    小 Q 现在想知道,当棋子从格点 0 出发,移动 N 步最多能经过多少格点。格点可以重复经过多次,但不重复计数。

    (color{#0066ff}{输入格式})

    第一行包含2个正整数V, N,其中 V 表示格点总数,N 表示移动步数。

    接下来V − 1行,每行两个数(a_i,b_i),表示编号为(a_i,b_i)的两个格点之间有连线。

    (color{#0066ff}{输出格式})

    输出一行一个整数,表示最多经过的格点数量。

    (color{#0066ff}{输入样例})

    5 2
    1 0
    2 1
    3 2
    4 3
        
    
        
        
    9 5
    0 1
    0 2
    2 6
    4 2
    8 1
    1 3
    3 7
    3 5
    

    (color{#0066ff}{输出样例})

    3
        
        
    5
    

    (color{#0066ff}{数据范围与提示})

    【输入输出样例 1 说明】

    从格点 0 出发移动 2 步。经过 0, 1, 2 这 3 个格点。

    【输入输出样例 2 说明】

    一种可行的移动路径为 0 → 1 → 3 → 5 → 3 → 7,经过 0, 1, 3, 5, 7 这 5 个格点。

    【数据规模与约定】

    对于 100%的测试点,N,V ≤ 100, (0 ≤a_i,b_i< V)

    (color{#0066ff}{题解})

    显然是个树形DP,然而我并不会。。

    考虑贪心qwq

    因为我们并不用回来,所以肯定是走一条最长链+一堆分支

    走分支走过去再回到主链上,所以答案就是最长链+(剩下的部分的一半)

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
        char ch; LL x = 0, f = 1;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
        return x * f;
    }
    const int maxn = 1e5 + 10;
    struct node {
        int to;
        node *nxt;
        node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
    };
    node *head[maxn];
    bool vis[maxn];
    int n, m, max;
    void add(int from, int to) { head[from] = new node(to, head[from]); }
    void dfs(int x, int fa, int dep) {
        max = std::max(max, dep);
        for(node *i = head[x]; i; i = i->nxt) 
            if(i->to != fa) 
                dfs(i->to, x, dep + 1);
    }
    int main() {
        n = in(), m = in();
        int x, y;
        for(int i = 1; i < n; i++) x = in() + 1, y = in() + 1, add(x, y), add(y, x);
        dfs(1, 0, 1);
        if(m + 1 > max) printf("%d
    ", std::min(n, max + ((m - max + 1) >> 1)));
        else printf("%d
    ", m + 1);
        return 0;
    }
    
  • 相关阅读:
    Firefly 介绍
    9秒社团跨平台开发引擎CrossApp宣布正式开源
    页面置换算法
    Selenium
    C++虚函数、虚继承
    链表题目
    二叉树分类
    求连续子数组的最大和
    拓扑排序
    二叉树题目
  • 原文地址:https://www.cnblogs.com/olinr/p/10626851.html
Copyright © 2011-2022 走看看