树学习笔记——处理边权
零、前言(胡说八道)
众所周知,在一棵已经有根的树上,处理点权是非常容易的,只要另外开一个数组记录每个点对应的权值即可。
但我们在学习有根树的过程中,经常会遇到某些题目给定了权值,给定的是边权,而不是点权。导致后面的算法处理这里时可能出现一些困难。(我在这里翻车了\(n\) 次)
因此,就出现了一些奇妙的方法,轻松存储或处理了边权。
一、方法
1、邻接表(链式前向星)
和图的邻接表一样,可以直接解决问题。
没啥可说的(逃)
ex:(核心代码)
int cnt = 0, head[105];
struct node{
int u, v, w, next;
}ed[505];
void add(int uu, int vv, int ww)
{
cnt++;
ed[cnt].u = uu; //父节点
ed[cnt].v = vv; //子节点
ed[cnt].w = ww; //这条边权值
ed[cnt].next = head[uu];
head[uu] = cnt;
}
2、vector + 结构体大法好!
\(vector\) 的类型并不只能是整型,当然也可以是结构体!
先独立写一个结构体,里面封装两个:一个节点,一个边权即可。(另一个节点是那一维)
每次存边的时候存\(2\) 个数。
ex:
struct node{
int v, w;
};
vector <node> g[105]; //这里的类型改成那个结构体的名称
...
int main()
{
int n, m;
cin >> n >> m;
...
for(int i = 1; i <= m; i++)
{
int x, y, z;
cin >> x >> y >> z;
g[x].push_back({y, z});//注意这里要与结构体内封装的变量个数一致,并且外面要加大括号
g[y].push_back({x, z});//因为这时两个节点并没有确立父子关系,所以两边全加
}
}
3、边权-->点权
我们已经知道了两点的父子关系,
那么,我们可以根据题目要求,把那条边权挂到父节点或子节点上。
比如,如果是求从根开始的树上前缀和,那就要把边权挂到子节点上去,这样对计算出的结果不会有影响。但如果是求从叶子节点开始的子树前缀和,那就要把边权挂到父节点上去。
代码不小心被吞掉了~