BZOJ1509 [NOI2003]逃学的小孩 树型DP
题目:
分析:
首先明确我们是要求 min(dist[C][A],dist[C][B])+dist[A][B].
我们把C当成树根,第一我们可以发现min里面取dist[C][A]或者dist[C][B]其实是一个意思(因为可以交换)。
接着可以发现dist[A][B]实际上是这棵树的直径。如果不是,那么答案一定不是最优的。我们可以这样去想:
如果dist[A][B]不是直径,那么一定有dist[C][A']使得比dist[C][A]更优,而且A'一定是直径的一个端点:-)。加号的前面和后面都不是最优的,那么答案也不是最优的。
所以我们可以先处理出树的直径,接着枚举点C使得它到两个端点的距离的最小值最大。
时间复杂度O(n),空间复杂度O(n)。
代码:
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<vector>
- using namespace std;
- typedef long long ll;
- struct edge{
- ll to,w;
- };
- const ll maxn = ;
- ll n,m;
- vector <edge> g[maxn];
- ll arr[maxn],dep[maxn];
- void dfs(int now,ll data){
- arr[now] = ;
- dep[now] = min(dep[now],data);
- for(int i=;i<g[now].size();i++){
- if(arr[g[now][i].to]) continue;
- dfs(g[now][i].to,g[now][i].w+data);
- }
- arr[now] = ;
- }
- int get_max(){
- dep[] = ;
- int maxx = ;
- for(int i=;i<=n;i++){
- if(dep[maxx] < dep[i]) maxx = i;
- }
- return maxx;
- }
- void read(){
- scanf("%lld%lld",&n,&m);
- for(ll i=;i<=m;i++){
- ll x,y,c; scanf("%lld%lld%lld",&x,&y,&c);
- g[x].push_back((edge){y,c});
- g[y].push_back((edge){x,c});
- }
- }
- void work(){
- memset(dep,/,sizeof(dep));
- dfs(,);//get the farthest point in tree
- ll ans=,t1 = get_max();
- memset(dep,/,sizeof(dep));
- dfs(t1,);//another point
- ll t2 = get_max();
- ans += dep[t2];//zhijing
- dfs(t2,);
- ll maxx = ;
- for(int i=;i<=n;i++)
- maxx = max(maxx,dep[i]);
- ans += maxx; // farthest dian for zhijing
- printf("%lld",ans);
- }
- int main(){
- read();
- work();
- return ;
- }
BZOJ1509 [NOI2003]逃学的小孩 树型DP的更多相关文章
- BZOJ 1509 逃学的小孩 - 树型dp
传送门 题目大意: 在一棵树中, 每条边都有一个长度值, 现要求在树中选择 3 个点 X.Y. Z , 满足 X 到 Y 的距离不大于 X 到 Z 的距离, 且 X 到 Y 的距离与 Y 到 Z 的距 ...
- BZOJ1509: [NOI2003]逃学的小孩(树的直径)
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1126 Solved: 567[Submit][Status][Discuss] Description ...
- BZOJ1509: [NOI2003]逃学的小孩 (树形DP)
题意:给一棵树 选三个点A,B,C 求A到B的再从B到C的距离最大值 需要满足AB的距离小于AC的距离 题解:首先树上的最大距离就想到了直径 但是被样例误导了TAT BC两点构成了直径 我一开始以为A ...
- BZOJ1509 NOI2003 逃学的小孩
Description: Input: 第一行是两个整数N(3 N 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的信息.第i+1行包含整数Ui.Vi.Ti(1 ...
- BZOJ 1509: [NOI2003]逃学的小孩( 树形dp )
树形dp求出某个点的最长3条链a,b,c(a>=b>=c), 然后以这个点为交点的最优解一定是a+2b+c.好像还有一种做法是求出树的直径然后乱搞... ----------------- ...
- 【BZOJ1509】[NOI2003]逃学的小孩 直径
[BZOJ1509][NOI2003]逃学的小孩 Description Input 第一行是两个整数N(3 N 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的 ...
- [NOI2003]逃学的小孩(树的直径)
[NOI2003]逃学的小孩 题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听 ...
- POJ3659 Cell Phone Network(树上最小支配集:树型DP)
题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...
- POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断
好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...
随机推荐
- Django中的MiddleWare中间件
1. middleware简介 Django的middleware的概念相当于SSH框架里面的filter的概念.中间键的作用就是对所有的request,在request前,和在response后做一 ...
- bzoj 1143 二分图最大独立集
我们可以将一个点拆成两个点x,y,那么如果存在一条i->j的路径,我们就连接xi,yj,那么答案就是n-最大匹配数. 因为i->j所以对于i与j只能选一个,那么我们只需要求出来二分图的最大 ...
- 有关mysql的innodb_flush_log_at_trx_commit参数【转】
一.参数解释 0:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行.该模式下在事务提交的时候,不会主动触发写入磁盘的操作. 1:每次事务 ...
- 转:mysql日志(Windows下开启Mysql慢查询、通用日志)
一.Windows下开启Mysql慢查询详解 //show variables like '%quer%';查询是否开启了慢查询!! 第一步:修改my.ini(mysql配置文件) 在my.ini中 ...
- CSS初步了解
CSS 概述 个人理解为对html的扩展,对html关键字进行功能添加. CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表 ...
- Otto:EventBus
Otto:EventBus 2014年6月20日 星期五 15:14 参考: http://www.mythroad.net/?p=4151 Otto 是Android系统的一个Event Bus模式 ...
- 反片语(UVa156)
题目具体描述见:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=835&a ...
- 【DEV C++】 Error: ld returned 1 exit status
一般出现“ld returned 1 exit status”错误都是由于函数名称拼写错误造成的,或者在一个工程中不同的函数使用了同一个函数名,暂时还未遇到其他情况.
- c++ primer 5 表达式
简单总结下容易忽视的地方和易错点吧 1 常用的位操作符,leecode很多算法题都是靠位运算解决的 2 箭头操作符 -> 等价于(* ). 对指针的成员操作 3 sizeof操作符 对 c ...
- 【C#日期系列(三)】--C#获取某个月的第一个星期几的年月日
需要获取某个月的第一个星期几的年月日 简单写了一个算法 #region 计算每月第一个星期1-7是各是几号 /// <summary> /// 计算每月第一个星期1-7是各是几号 /// ...