最小生成树 无根树转有根树 树形动态规划
最小生成树 & 无根树转有根树 & 树形动态规划
- 最小生成树
- 定义
- 概念
- 个人理解
- 应用
- 解决方法
- 例题(luogu P3366 【模板】最小生成树)
- 题目描述
- 输入
- 输出
- 做法
- 如何判环
- 代码
- 无根树转有根树
- 方法
- 将最小生成树(无根树)转化成有根树
- 代码
- 树形动态规划
- 定义
- 个人理解
- 例题(luogu P1352 没有上司的舞会)
- 题目描述
- 解决
- 代码
- xiexie.
最小生成树
定义
概念
一个有 nnn 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 nnn 个结点,并且有保持图连通的最少的边。 —摘自百度百科
个人理解
最小生成树就是在一张图中找到一棵所有n−1n-1n−1条边的权值之和最小,最小生成树可能不止一棵。
应用
适用于城市之间最小费用等问题。
解决方法
例题(luogu P3366 【模板】最小生成树)
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出
7
样例解释:
所以最小生成树的总边权为2+2+3=72+2+3=72+2+3=7.
做法
不难想到先将所有的权值从小到大排个序,然后最小的那条边一定是在最小生成树里面,当加入的这条边可以使当前的最小生成树出现环时,则跳过不能加进来。如果没有出现环,则把这条边加到这课最小生成树里,一直加到n−1n-1n−1条边加完为止(根据树的基本性质,所以nnn条边有n−1n-1n−1个点),这些操作完成后,这个最小生成树权值之和就是答案。
如何判环
利用并查集,将满足的边加入最小生成树时,同时加入同一个并查集(记录)。当不满足时,只需要判断点是否在并查集中,若在,则不能加进来,否则就加进来。
代码
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
int n,m;
queue<int>q;
struct node1{int x,y,z;
}edge[200001];
struct Edges{int to,w;};
vector<Edges>d[5001];
void add(int a,int b,int c){d[a].push_back((Edges){b,c});d[b].push_back((Edges){a,c});
}
int cmp(node1 a,node1 b){return a.z < b.z;
}
int fa[5001];
int getfa(int x){if(x == fa[x])return x;return fa[x] = getfa(fa[x]);
}
int ans = 0,a[5001],tot;
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);}sort(edge+1,edge+m+1,cmp);for(int i=1;i<=n;i++)fa[i] = i;for(int i=1;i<=m;i++){if(getfa(edge[i].x)!=getfa(edge[i].y)){fa[getfa(edge[i].x)] = getfa(edge[i].y);ans+=edge[i].z;add(edge[i].x,edge[i].y,edge[i].z);}}printf("%d\n",ans);return 0;
}
无根树转有根树
这是一个技巧!
对于树形dp很有用。
方法
只要把无根树任意一个节点当成是根,然后遍历整个树即可。
将最小生成树(无根树)转化成有根树
题面方法同上。
代码
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
int n,m;
queue<int>q;
struct node1{int x,y,z;
}edge[200001];
struct Edges{int to,w;};
vector<Edges>d[5001];
void add(int a,int b,int c){d[a].push_back((Edges){b,c});d[b].push_back((Edges){a,c});
}
int cmp(node1 a,node1 b){return a.z < b.z;
}
int fa[5001];
int getfa(int x){if(x == fa[x])return x;return fa[x] = getfa(fa[x]);
}
int ans = 0,a[5001],tot;
void dfs(int u,int pre){//该操作a[++tot]=u;for(int i=0;i<d[u].size();i++){int v = d[u][i].to;if(pre!=v) dfs(v,u);}
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);}sort(edge+1,edge+m+1,cmp);for(int i=1;i<=n;i++)fa[i] = i;for(int i=1;i<=m;i++){if(getfa(edge[i].x)!=getfa(edge[i].y)){fa[getfa(edge[i].x)] = getfa(edge[i].y);ans+=edge[i].z;add(edge[i].x,edge[i].y,edge[i].z);}}dfs(1,-1);printf("%d\n",ans);for (int i=1;i<=tot;i++) printf("%d ",a[i]);//输出有根树遍历return 0;
}
树形动态规划
定义
树形动态规划问题可以分解成若干相互联系的阶段,在每一个阶段都要做出决策,全部过程的决策是一个决策序列。要使整个活动的总体效果达到最优的问题,称为多阶段决策问题。 —摘自百度百科
个人理解
在图上动态规划,往往要在树上进行。
例题(luogu P1352 没有上司的舞会)
题目描述
某大学有 nnn 个职员,编号为 1…n1 \ldots n1…n。
他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。
现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数rir_iri
,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。
所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
解决
根据建模类似线性动态规划得出状态转移方程。
我们设f[u][1]f[u][1]f[u][1]为当前人选择去的快乐值得最优情况。
f[u][0]f[u][0]f[u][0]为当前人不选去的快乐值得最优情况。
则:(vvv为当前点)
f[u][1]=∑f[v][0].f[u][1] = \sum{f[v][0]}. f[u][1]=∑f[v][0].
f[u][0]=∑max(f[v][0],f[v][1]).f[u][0] = \sum{max(f[v][0],f[v][1])}. f[u][0]=∑max(f[v][0],f[v][1]).
在这之前由题目可知需要先找根。
代码
#include<cstdio>
#include<vector>
using namespace std;
struct node{int to;};
vector<node>edges[6001];
int N,r[6001],sum,f[6001][2];
void dfs(int u){f[u][1] = r[u];for(int i=0;i<edges[u].size();i++){dfs(edges[u][i].to);f[u][1] += f[edges[u][i].to][0];f[u][0] += max(f[edges[u][i].to][0],f[edges[u][i].to][1]);}
}
int main(){scanf("%d",&N);for(int i=1;i<=N;i++){scanf("%d",r+i);sum ^= i;}for(int i=1;i<N;i++){int a,b;scanf("%d%d",&a,&b);edges[b].push_back((node){a});sum ^= a;}dfs(sum);printf("%d",max(f[sum][0],f[sum][1]));return 0;
}
答案就是max(f[sum][0],f[sum][1])max(f[sum][0],f[sum][1])max(f[sum][0],f[sum][1])
xiexie.
最小生成树 无根树转有根树 树形动态规划相关推荐
- 一本通提高篇 树形动态规划
先写个考试 鸽着~ 考试有树 d p dp dp紫题 我回来了 每年联赛基本都有好几道题时树 d p dp dp,这块一定得好好学 U P D : 20201109 UPD:20201109 UPD: ...
- HDU1520 Anniversary party 树形动态规划
HDU1520 Anniversary party 树形动态规划 Anniversary party Time Limit: 2000/1000 MS (Java/Others) Memory ...
- Facebook Hacker Cup 2015 Round 1--Corporate Gifting(树形动态规划)
原题:https://www.facebook.com/hackercup/problems.php?pid=759650454070547&round=344496159068801 题意: ...
- 蓝桥杯 算法训练(四)结点选择(树形动态规划)
结点选择(树形动态规划)C语言 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一 ...
- c++ 不撞南墙不回头——树形动态规划(树规)
不撞南墙不回头--树规总结 焦作一中信息学oy 之所以这样命名树规,是因为树规的这一特殊性:没有环,dfs是不会重复,而 ...
- 不撞南墙不回头——树形动态规划(树规)
不撞南墙不回头--树规总结 焦作一中信息学oy 之所以这样命名树规,是因为树规的这一特殊性:没有环,dfs是不会重复,而 ...
- 假如我是儿子——树形动态规划
--来自焦作一中卢裕东 想给这篇总结起个霸气又有意义的名字,翻来覆去,想到了今年暑假在郑州的NOIP夏令营,朱全民老师讲树规时说的一句惊天动地的话,那时给我们举例子,就有了这句:假如我是儿子!好吧,我 ...
- 小H和游戏(无根树转有根树,思维)难度⭐⭐⭐★
链接:https://ac.nowcoder.com/acm/contest/5203/D 来源:牛客网 题目描述 小H正在玩一个战略类游戏,她可以操纵己方的飞机对敌国的N座城市(编号为1~N)进行轰 ...
- 树形动态规划之树的最大独立集
树的最大独立集 对于一颗n个结点的无根树,选出尽量多的的结点,使得任何两个结点均不相邻(称为最大独立集),然后输入n-1条无向边,输出一个最大独立集(如果有多解,则任意输出一组). 分析: 用d(i) ...
- POJ2486POJ3659 ——树形动态规划
两道题都折腾了很长时间,总算过了.树形动规,主要在于动规顺序,其次才是状态的设计. POJ2486: 先用左儿子右兄弟表示法进行多叉转二叉. f[i][j]表示从i点出发走了j步.最后不一定要回到i点 ...
最新文章
- sql中like带参数的写法
- IOS开发之--UIScrollView pagingEnabled自定义翻页宽度
- JavaME:Google静态地图API
- android蓝牙4.0使用方法
- resin指定java版本_resin的几个常用配置
- python特性 property_python之中特性(attribute)与属性(property)有什么区别?
- java图片简单爬虫_[Java教程]使用jsoup进行简单的爬虫操作爬取图片
- 选中连线的话,整个连线会显示在一个框里面
- 深入Hadoop磁盘部署的算法
- window10查看内存情况
- MENTOR PADS软件菜单显示不完整?这里有妙招
- ITIL学习笔记——ITIL入门小知识
- win10系统通过关键字快速搜索文件内容的软件
- 专升本-计算机公共课考点(5)——演示文稿软件 PowerPoint 2010
- mysql indentify_ORA-01157: cannot identify/lock data file导致表空间无法on
- Navigation网站收藏和导航平台
- python处理Excel实现自动化办公教学(数据筛选、公式操作、单元格拆分合并、冻结窗口、图表绘制等)【三】
- 天嵌i.mx6q开发板android4.3编译问题
- 问题 C: Fraction 分数类 I
- U盘写保护无法格式化
热门文章
- 论文阅读:Factorizable Net: An Efficient Subgraph-based Framework for Scene Graph Generation
- Excel中如何把数字设置成以万为单位
- 操作性定义(Operational Definition)
- Mathematica实现0.618法(黄金分割法)求最大最小值
- docker network详解、教程
- STM32单片机蜂鸣器实验
- 10分钟教你阿里云环境下搭建iredmail邮件服务器
- 安徽科技学院 信网学院网络文化节 陈鑫鑫
- 实验题集4:函数R6-1 面积计算器(函数重载) (10 分)
- 假设检验1——理论基础