zoukankan      html  css  js  c++  java
  • Codeforces Round #328 (Div. 2) D. Super M

    题目链接:

    http://codeforces.com/contest/592/problem/D

    题意:

    给你一颗树,树上有一些必须访问的节点,你可以任选一个起点,依次访问所有的必须访问的节点,使总路程最短。

    题解:

    由于是树,任意两点间路径唯一,是确定的。

    首先我们要先建一颗树:包括所有必须访问的节点,已经它们之间的路径。

    我们选的起点一定是某个必须访问的节点,如果我们把所有的必须访问的节点访问一遍并且回到起点,那么我们用的最小花费就是边数*2(这个可以用反证法证明),所以只要我们找出新树的直径,答案就是边数*2-直径。

    (官方题解)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    int n, m;
    vector<int> G[maxn];
    int ans,ans1,ans2,dis;
    bool tag[maxn];
    
    //两次dfs求最远顶点对
    void dfs(int u,int fa,int d,int& res) {
        if (dis < d&&tag[u]) {
            dis = max(dis, d);
            res = u;
        }
        if (dis == d&&tag[u]) res = min(res, u);
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (v == fa) continue;
            dfs(v, u, d + 1, res);
        }
    }
    
    bool used[maxn];
    int _cnt;
    //求虚拟树的节点数
    bool dfs2(int u, int fa) {
        if (tag[u]) used[u]=1;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (v == fa) continue;
            used[u] |= dfs2(v, u);
        }
        if (used[u]) _cnt++;
        return used[u];
    }
    
    int main() {
        memset(tag, 0, sizeof(tag));
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n - 1; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        ans = INF;
        for (int i = 0; i < m; i++) {
            int v;
            scanf("%d", &v);
            tag[v] = 1;
            ans = min(ans, v);
        }
        if (m == 1) {
            printf("%d
    %d
    ", ans, 0);
            return 0;
        }
        dis = -1, ans1 = INF;
        dfs(ans, -1, 0,ans1);
        dis = -1, ans2 = INF;
        dfs(ans1, -1, 0, ans2);
    
        memset(used, 0, sizeof(used));
        _cnt = 0;
        dfs2(ans1, -1);
        int res = (_cnt - 1) * 2 - dis;
        printf("%d
    %d
    ", min(ans1, ans2), res);
        return 0;
    }
  • 相关阅读:
    HTML相关
    190. 颠倒二进制位【简单】
    22. 括号生成【中等】
    83. 删除排序链表中的重复元素【简单】
    vuejs2.0声明周期
    js增加8小时
    获取DOM的原生事件对象
    hive创建表失败:FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaEx
    安装hive过程填坑小结
    CentOS 7配置网络,静态IP
  • 原文地址:https://www.cnblogs.com/fenice/p/5572432.html
Copyright © 2011-2022 走看看