博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 3289 Magic tree (最大生成树 + dfs +树状数组)
阅读量:5043 次
发布时间:2019-06-12

本文共 1560 字,大约阅读时间需要 5 分钟。

题意:对一棵树上的点进行实时的增减权值和询问子树的权值和

首先:单点修改以及子树查询。对整棵树dfs一遍,记录下欧拉序列。这样有一个好处,就是每一棵子树在这个序列中都是连续的,同时记录下每一棵子树的起始序列号,这样,对子树的查询就变成了一个连续区间的查询了,运用树状数组就可以解决了。

那最大生成树呢?“Sailormoon girls want to cut extra branches by using minimum cost, after that..."额,这里要将多余的边减掉,用最小cost,也就是减掉之后,变成了一棵最大生成树。郁闷呀,一开始以为题目所给的cost是没用…………

View Code
#include
#include
#include
#include
using namespace std; const int MAXN = 100010; int spos[MAXN],epos[MAXN],sum[MAXN],w[MAXN]; int n,f[MAXN],index; bool vis[MAXN]; struct edge {
int u,v,w; edge(int a=0,int b=0,int c=0):u(a),v(b),w(c){} bool friend operator<(const edge a,const edge b) {
return a.w
Q; vector
g[MAXN]; void init() { for(int i=0;i<=n;i++) { f[i]=i; w[i]=sum[i]=0; g[i].clear(); } } int find(int x) { if(x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } void Union(int x,int y) { int a=find(x); int b=find(y); if(a==b) return ; f[a]=b; g[x].push_back(y);//重新构建树 g[y].push_back(x); } void Kruskal()//将所有边压入优先队列,再取出所有边合并,求最大生成树 { while(!Q.empty()) { Union(Q.top().u,Q.top().v); Q.pop(); } } int lowbit(int x)//这里往下三个函数就是树状数组的模板函数了,就不多说了 { return x&(-x); } void modify(int x,int add) { while(x<=n) { sum[x]+=add; x+=lowbit(x); } } int get_sum(int x) { int ret=0; while(x!=0) { ret+=sum[x]; x-=lowbit(x); } return ret; } void dfs(int u) { spos[u]=index;//记录子树的起始位置 vis[u]=true; for(int i=0;i

 

转载于:https://www.cnblogs.com/nanke/archive/2012/02/26/2368818.html

你可能感兴趣的文章