zoukankan      html  css  js  c++  java
  • HDU 4607 Park Visit(树的直径)

    题目大意:给定一棵树,让求出依次访问k个点的最小花费,每条边的权值都为1.

    思路:如果能一直往下走不回来,那么这个路径肯定是最小的,这就取决于给定的k,但是怎么确定这个能一直走的长度呢,其实这个就是树的直径,也叫作最长简单路径。找出来这个直径之后,只需和k比较一下就能确定走多少步。设直径为maxx, 如果maxx + 1== k的话,说明刚好不用回来走完最长的这个路,所以当k小于等于maxx + 1的时候就是k-1,当k大于maxx + 1的时候,除了要走完不用回来的路,肯定还要走那些用回来的,剩下的要回来的个数是k-maxx-1,这些都走两遍,所以乘以二就行了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef pair<int, int> pii;
    const int maxn = 220000;
    int tot, head[maxn];
    struct Edge {
        int to, next;
    }edge[maxn];
    bool vis[maxn];
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int maxx, pos;
    void bfs(int p)//广搜找出离p最远的那个点 
    {
        maxx = 0;
        memset(vis, false, sizeof(vis));
        queue<pii> Q;
        pii cur, nex;
        cur.first = p; cur.second = 0;
        vis[p] = true;
        Q.push(cur);
        while (!Q.empty())
        {
            cur = Q.front();
            Q.pop();
            for (int i = head[cur.first]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if (vis[v]) continue;
                vis[v] = true;
                nex.first = v; nex.second = cur.second + 1;
                if (maxx < nex.second)
                {
                    maxx = nex.second;//最远的距离保存在maxx中 
                    pos = v;//最远的那个点保存在pos中 
                }
                Q.push(nex);
            }
        }
    }
    int main()
    {
        int T, n, m;
        scanf("%d", &T);
        while (T--)
        {
            init();
            int u, v;
            scanf("%d %d", &n, &m);
            for (int i = 1; i < n; i++)
            {
                scanf("%d %d", &u, &v);
                addedge(u, v);
                addedge(v, u);
            }
            bfs(1);
            bfs(pos);
            int k;
            for (int i = 0; i < m; i++)
            {
                scanf("%d", &k);
                if (k - 1 <= maxx)
                    printf("%d
    ", k - 1);
                else
                    printf("%d
    ", maxx + (k - maxx - 1) * 2);
            }
        }
        
        return 0;
    } 
  • 相关阅读:
    在MS Sql Server中可以能过以下的方法查询出磁盘空间的使用情况及各数据库数据文件及日志文件的大小及使用利用率:
    sqlserver日志的备份与还原
    C#中String 与Color之间的相互转换
    sql 替换字符串
    Components_Box
    射线检测与碰撞通道设置
    切碎方块
    音乐可视化
    枚举
    UI与Actor(蓝图)的互动
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4779291.html
Copyright © 2011-2022 走看看