题意:

给出一个树,树上每一条边的边权为 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. POJ - 2186  Popular Cows tarjain模板题

    http://poj.org/problem?id=2186 首先求出所有的强连通分量,分好块.然后对于每一个强连通分量,都标记下他们的出度.那么只有出度是0 的块才有可能是答案,为什么呢?因为既然你 ...

  2. Storm编程入门API系列之Storm的Topology多个tasks数目控制实现

    前期博客 Storm编程入门API系列之Storm的Topology默认Workers.默认executors和默认tasks数目 Storm编程入门API系列之Storm的Topology多个Wor ...

  3. Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果

    建立一个基本的屏幕后处理脚本系统 屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效.使用这种技术,可以为游戏画面添加更多艺术效果,例如景深. ...

  4. 自定义xml配置文件之dtd文件校验

    用了很多第三方库,也看了些源码,总是想如果自己写一个类似的库,读取xml配置文件(properties配置文件比较简单) 该如何给配置文件添加头,添加校验,因为xml配置文件相对于properties ...

  5. ASP.NET AJAX入门系列(5):使用UpdatePanel控件(二)

    UpdatePanel可以用来创建丰富的局部更新Web应用程序,它是ASP.NET 2.0 AJAX Extensions中很重要的一个控件,其强大之处在于不用编写任何客户端脚本,只要在一个页面上添加 ...

  6. jQuery deferred应用之ajax详细源码分析(二)

    在上一节中,我只贴出了$.Deferred的源码分析,并没用讲解怎么使用它,现在我们先看看$.ajax是如何使用它,让我们进行异步任务的处理. 如果没看上节的代码,请先稍微了解一下jQuery Def ...

  7. nmon各配置项含义介绍

    1)nmon各配置项含义介绍

  8. 我用ABAP做过的那些无聊的事情

    国庆大假马上就要来临了,我们聊点轻松的话题,关于假期. Jerry的成都同事李贝宁(Li Ben), <SAP成都研究院李三郎:SCP Application Router简介>的作者,有 ...

  9. Java动态代理之InvocationHandler最简单的入门教程

    网上关于Java的动态代理,Proxy和InvocationHandler这些概念有讲解得非常高深的文章.其实这些概念没有那么复杂.现在咱们通过一个最简单的例子认识什么是InvocationHandl ...

  10. 如何修改IOS的默认字体

    The first is workaround wich is iterating over all the labels in your UIView and change the labels f ...