题意:

给出一个树,树上每一条边的边权为 1,求树上所有最长链的点集并。

细节:

可能存在多条最长链!最长链!最长链!重要的事情说三遍

分析:

方法round 1:暴力乱搞Q A Q,边权为正-> d f s 解决,如何标记点集呢,只需要求出最大长度,然后在进行一次遍历,当当前长度等于最长链长的时候就返回 true,并且对沿路的节点进行标记。

好吧这样你就成功的死亡了,还是细节最长链有多条!有多条!有多条!好吧我们再来看一张神奇的图片

点我的最帅最美

想象一下多条最长链一定是根所示的有一条链和一些在同方向的等长的分支组成,所以只 D F S 一次必然在同方向的分支必然不会被标记,所以只要 D F S 两次就好了。

方法round 2:树形 Dp 个人感觉比较反人类,在记录次长和最长的链之外我们只需要在记录一个 f[u][2] 表示距离 u 最远的节点,最后只要统计某个点的最长链是否等于最长链即可。

最后献上一波转移:

if (f[v][0]+1!=f[u][0] || (f[v][0]+1==f[u][0] && cnt>1)) f[v][2]=max(f[u][2], f[u][0])+1;

else f[v][2]=max(f[u][2], fu)+1;


cnt 是某节点儿子节点数

代码:

Round1:

#include<bits/stdc++.h>
#define MAXN 200010
using namespace std; vector<int> Right[MAXN];
int n, dist[MAXN];
bool flag[MAXN]; void dfs(int u, int fa){
for (int i=0; i<Right[u].size(); i++){
int v=Right[u][i];
if (v==fa) continue;
dist[v]=dist[u]+1;
dfs(v, u);
}
} bool solve(int u, int fa, int now, int Max){
for (int i=0; i<Right[u].size(); i++){
int v=Right[u][i];
if (v==fa) continue;
flag[u]|=solve(v, u, now+1, Max);
}
if (now==Max) {
flag[u]=1;
return flag[u];
}
else return flag[u];
} int main(){
scanf("%d", &n);
for (int i=1, x, y; i<n; i++){
scanf("%d%d", &x, &y);
Right[x].push_back(y);
Right[y].push_back(x);
}
memset(dist, 0, sizeof dist);
dfs(0, -1);
int Max=0, maxnum;
for (int i=0; i<n; i++)
if (dist[i]>Max) Max=dist[i], maxnum=i;
memset(dist, 0, sizeof dist);
dfs(maxnum, -1);
Max=0;
int Maxnum;
for (int i=0; i<n; i++)
if (dist[i]>Max) Max=dist[i], Maxnum=i;
solve(maxnum, -1, 0, Max);
solve(Maxnum, -1, 0, Max);
for (int i=0; i<n; i++)
if (flag[i]) printf("%d\n", i);
return 0;
}
Round2:

#include<bits/stdc++.h>
#define MAXN 200010
using namespace std; int f[MAXN][3], n;
vector<int> Right[MAXN]; void Tree_Dp(int u, int fa){
for (int i=0; i<Right[u].size(); i++){
int v=Right[u][i];
if (v==fa) continue;
Tree_Dp(v, u);
if (f[v][0]+1>f[u][0]) f[u][1]=f[u][0], f[u][0]=f[v][0]+1;
else if (f[v][0]+1>f[u][1]) f[u][1]=f[v][0]+1;
}
} void solve(int u, int fa){
int cnt=0;
for (int i=0; i<Right[u].size(); i++){
int v=Right[u][i];
if (v==fa) continue;
if (f[v][0]+1==f[u][0]) cnt++;
}
for (int i=0; i<Right[u].size(); i++){
int v=Right[u][i];
if (v==fa) continue;
if (f[v][0]+1!=f[u][0] || (f[v][0]+1==f[u][0] && cnt>1)) f[v][2]=max(f[u][2], f[u][0])+1;
else f[v][2]=max(f[u][2], f[u][1])+1;
solve(v, u);
}
} int main(){
scanf("%d", &n);
for (int i=1, x, y; i<n; i++){
scanf("%d%d", &x, &y);
Right[x].push_back(y);
Right[y].push_back(x);
}
Tree_Dp(0, -1);
int Max=0;
for (int i=0; i<n; i++) Max=max(Max, f[i][0]+f[i][1]);
solve(0, -1);
for (int i=0; i<n; i++)
if (f[i][0]+max(f[i][1], f[i][2])==Max) printf("%d\n", i);
return 0;
}

VIJOS1476 旅行规划(树形Dp + DFS暴力乱搞)的更多相关文章

  1. VIJOS1476旅游规划[树形DP 树的直径]

    描述 W市的交通规划出现了重大问题,市政府下决心在全市的各大交通路口安排交通疏导员来疏导密集的车流.但由于人员不足,W市市长决定只在最需要安排人员的路口安放人员.具体说来,W市的交通网络十分简单,它包 ...

  2. 树形DP+贪心(乱搞)(HDU4714)

    题意:给出一个树形图,要求把该树形成一个环最少的步骤(断开一条边和形成一条边都需一步) 分析:很明显,要想把树形成一个环,就要先把其分裂成m条子链之后把子链形成环需要的步骤是2*m+1,所以只需要m最 ...

  3. HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca

    Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...

  4. P1642 规划 01分数规划+树形DP

    $ \color{#0066ff}{ 题目描述 }$ 某地方有N个工厂,有N-1条路连接它们,且它们两两都可达.每个工厂都有一个产量值和一个污染值.现在工厂要进行规划,拆除其中的M个工厂,使得剩下的工 ...

  5. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  6. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  7. poj 3140 Contestants Division(树形dp? dfs计数+枚举)

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

  8. 树的直径的求法即相关证明【树形DP || DFS】

    学习大佬:树的直径求法及证明 树的直径 定义: 一棵树的直径就是这棵树上存在的最长路径. 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之间的距 ...

  9. 刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)

    题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There ar ...

随机推荐

  1. 115 Distinct Subsequences 不同子序列

    给定一个字符串 S 和一个字符串 T,求 S 的不同的子序列中 T 出现的个数.一个字符串的一个子序列是指:通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串.(譬如," ...

  2. 110 Balanced Binary Tree 平衡二叉树

    给定一个二叉树,确定它是高度平衡的.对于这个问题,一棵高度平衡二叉树的定义是:一棵二叉树中每个节点的两个子树的深度相差不会超过 1.案例 1:给出二叉树 [3,9,20,null,null,15,7] ...

  3. mysql自己编写启停脚本

    一.场景 在实际生产环境中要求相对较高的企业对于root权限管控相对比较高,故而很多软件并非安装在root用户下(当然root用户权限也可管理,但正常情况下root权限并不会给业务使用方,而会给一个普 ...

  4. 推荐一个VPS

    有日本节点,不贵,用了两个月,感觉不错 http://www.vultr.com/?ref=6847480

  5. Bingding模型

    public abstract class Binding : IDefaultCommunicationTimeouts public virtual IChannelListener<TCh ...

  6. C#入门笔记2 变量

    变量关系到数据的存储,一个供程序操作的存储区的名字,每一个变量都一个特定的类型,类型决定变量的内存大小和布局. 注:必须一定要先声明,赋值后,才能使用. 变量声明 三种声明方式: 1.先声明,后赋值. ...

  7. js作用域及对象以及一些常用技巧

    回顾 流程控制(语句) 分支 if () {    }​if () {    } else {    }​if () {    } else if () {    } else if () {     ...

  8. 从零开始利用vue-cli搭建简单音乐网站(二)

    1.利用vue-router实现页面跳转 程序可以正常运行之后,下面我们需要配置路由实现页面的局部刷新,这一功能将用来实现网站页面的跳转. 打开程序目录,进入"src\router\inde ...

  9. powershell 根据错误GUID查寻错误详情

    使用azurepowershell 部署模板时,碰到了下面类似的问题: The template deployment 'ExampleDeployment-' is not valid accord ...

  10. IOS typedef 函数指针的用法

    代码简化, 促进跨平台开发的目的. typedef 行为有点像 #define 宏,用其实际类型替代同义字. 不同点:typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换. 用 ...