博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 4607 Park Visit (DP最长链)
阅读量:4628 次
发布时间:2019-06-09

本文共 2166 字,大约阅读时间需要 7 分钟。

题目】题意:N个城市形成一棵树,相邻城市之间的距离是1,问访问K个城市的最短路程是多少,共有M次询问(1 <= N, M <= 100000, 1 <= K <= N)。 【
思路】 访问K个城市的路线: 可以发现它由一条主线和若干支线构成,并且主线上的边只用访问一次,而支线上的边必须且只用访问两次。而题目给定的是一棵树,那么访问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\n", tmp - 1);            }            else{                printf("%d\n", maxlen + 2*(tmp-1-maxlen));            }        }    }    return 0;}

转载于:https://www.cnblogs.com/AbandonZHANG/p/4114059.html

你可能感兴趣的文章
java常见题目总结
查看>>
(六) 牛顿切线法求根
查看>>
查看线程的运行状态
查看>>
MYSQL语句
查看>>
判断类之间的父子关系
查看>>
读书笔记——《黑客大曝光》(1/8)
查看>>
java基础小总结(2)
查看>>
HDU(1847)Good Luck in CET-4 Everybody!
查看>>
unity中的UI状态机,用于各界面之间的切换和跳转
查看>>
tar命令-压缩,解压缩文件
查看>>
bootstrap 冻结表格,冻结表头
查看>>
Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)
查看>>
Centos修改系统语言
查看>>
仿人智能控制器的参数简化(已发表于《计算机测量与控制》2013年第4期)
查看>>
Flink学习笔记:Operators之CoGroup及Join操作
查看>>
TSP问题——动态规划
查看>>
kmp练习
查看>>
python xml模块学习
查看>>
[WCF] - Odata Service 访问失败,查看具体错误信息的方法
查看>>
【2019/4/30】周进度报告
查看>>