zoukankan      html  css  js  c++  java
  • HDU 4607 Park Visit (DP最长链)

    题目】题意:N个城市形成一棵树,相邻城市之间的距离是1,问访问K个城市的最短路程是多少,共有M次询问(1 <= N, M <= 100000, 1 <= K <= N)。 【思路】 访问K个城市的路线: HDU 4607 可以发现它由一条主线和若干支线构成,并且主线上的边只用访问一次,而支线上的边必须且只用访问两次。而题目给定的是一棵树,那么访问K的城市就必须且仅需要走K-1条边。总边数是固定的,我们只需要保证主线最长即可,所以就是在树中找最长链。 【找最长链】树形dp,dp[i]表示他的子树的最大深度。选一个树根开始访问,每次访问完根节点的子树都要找出子树中深度最深的两个,把他们加起来更新最长链长度。并且留下最深的深度+1当作根节点的深度。  
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MID(x,y) ((x+y)/2)
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int MAXN = 200005;
    struct node{
        int u, v;
        int next;
    }arc[MAXN];
    int en, head[MAXN];
    void init(){
        en = 0;
        mem(head, -1);
    }
    void insert(int u, int v){
        arc[en].u = u;
        arc[en].v = v;
        arc[en].next = head[u];
        head[u] = en ++;
    }
    int dp[MAXN];
    int maxlen;
    bool vis[MAXN];
    void dfs(int u){
        vis[u] = 1;
        int max1 = 0, max2 = 0;
        int num = 0;
        for (int i = head[u]; i != -1; i = arc[i].next){
            int v = arc[i].v;
            if (!vis[v]){
                num ++;
                dfs(v);
                if (dp[v] > max1){
                    max2 = max1;
                    max1 = dp[v];
                }
                else{
                    if (dp[v] > max2){
                        max2 = dp[v];
                    }
                }
            }
        }
        if (0 == num){
            dp[u] = 0;
        }
        else{
            if (num == 1)
                maxlen = max(maxlen, max1+1);
            else
                maxlen = max(maxlen, max1+max2+2);
            dp[u] = max1 + 1;
        }
        return ;
    }
    int main(){
        //freopen("test.in", "r", stdin);
        //freopen("test.out", "w", stdout);
        int t;
        scanf("%d", &t);
        while(t --){
            init();
            int n, m;
            scanf("%d %d", &n, &m);
            for (int i = 0; i < n - 1; i ++){
                int u, v;
                scanf("%d %d", &u, &v);
                insert(u, v);
                insert(v, u);
            }
            mem(vis, 0);
            mem(dp, 0);
            maxlen = 0;
            dfs(1);
            for (int i = 0; i < m; i ++){
                int tmp;
                scanf("%d", &tmp);
                if (tmp - 1 <= maxlen){
                    printf("%d
    ", tmp - 1);
                }
                else{
                    printf("%d
    ", maxlen + 2*(tmp-1-maxlen));
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    python路径相关
    python之json
    python之正则表达式备忘
    MD5 SHA1 HMAC HMAC_SHA1区别
    微信根据openid给用户发送图文消息
    最近做的几个小程序
    5000万pv小程序,高并发及缓存优化,入坑
    小程序 后台发送模板消息
    mysql 组合索引
    php 拆分txt小说章节保存到数据库
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114059.html
Copyright © 2011-2022 走看看