【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6060

【题目大意】

  给一个n个节点的树,要求将2-n号节点分成k部分,
  然后将每一部分加上节点1,求每个集合最小斯坦纳树的最大权值和。

【题解】

  我们按照后序遍历染色分组,得到的一定是最优分组,
  现在考虑在不同颜色的虚树上求路径权值和,
  我们发现每个点增加的权值是深度减去到根的路径上已被覆盖的长度,
  这个长度等于与dfs序前继的LCA的深度,因此我们在搜索的同时计算与dfs序前继的LCA即可。

  But,发现多校题解完全不是我想的这样子。对于每条边来说,他的贡献值是min(k,size),然后dfs一遍即可,实现也很是简单。

  Amazing

【代码】

#include <cstdio>
#include <algorithm>
#include <list>
#include <vector>
using namespace std;
const int N=1000010;
typedef long long LL;
LL d[N];
int f[N],lst[N],c[N],st[N],en[N],dfn,size[N],son[N];
vector<int> v[N],w[N];
namespace fastIO{
#define BUF_SIZE 100000
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend){
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1){
IOerror=1;
return -1;
}
}return *p1++;
}
inline bool blank(char ch){
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}
inline bool read(int &x){
char ch;
while(blank(ch=nc()));
if(IOerror)return false;
for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');
return true;
}
#undef BUF_SIZE
};
int n,m,x,y,z;
int cnt,D[N],top[N];
LL ans;
void dfs(int x){
size[x]=1;
for(int i=0;i<v[x].size();i++){
int y=v[x][i];
if(y==f[x])continue;
f[y]=x; D[y]=D[x]+1;
dfs(y); size[x]+=size[y];
if(size[y]>size[son[x]])son[x]=y;
}cnt++;
if(cnt>m)cnt=1;
c[x]=cnt;
}
void dfs1(int x,int y){
if(x==-1)return;
st[x]=++dfn; top[x]=y;
if(son[x])dfs1(son[x],y);
for(int i=0;i<v[x].size();i++)if(v[x][i]!=son[x]&&v[x][i]!=f[x])dfs1(v[x][i],v[x][i]);
en[x]=dfn;
}
int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(D[top[x]]<D[top[y]]){int z=x;x=y;y=z;}
return D[x]<D[y]?x:y;
}
void dfs2(int x){
int cx=c[x];
if(lst[cx]){
int y=lst[cx];
y=lca(x,y);
ans+=d[x]-d[y];
}else ans+=d[x];
lst[cx]=x;
for(int i=0;i<v[x].size();i++){
int y=v[x][i],z=w[x][i];
//printf("--%d %d\n",y,z);
if(y==f[x])continue;
d[y]=d[x]+z;
dfs2(y);
}
}
using namespace fastIO;
int main(){
while(read(n)){
read(m); ans=0;
for(int i=1;i<=n;i++)v[i].clear(),w[i].clear(),lst[i]=0,son[i]=-1;
for(int i=1;i<n;i++){
read(x); read(y); read(z);
v[x].push_back(y);
v[y].push_back(x);
w[x].push_back(z);
w[y].push_back(z);
}dfn=cnt=0;
dfs(1); c[1]=0;
dfs1(1,1);
dfs2(1);
printf("%lld\n",ans);
}return 0;
}

HDU 6060 RXD and dividing(LCA)的更多相关文章

  1. HDU 6060 RXD and dividing(dfs 思维)

    RXD and dividing Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Other ...

  2. HDU 6060 RXD and dividing(思维+计算贡献值)

    http://acm.hdu.edu.cn/showproblem.php?pid=6060 题意: 给定一棵 n 个节点的树,1 为根.现要将节点 2 ~ n 划分为 k 块,使得每一块与根节点形成 ...

  3. HDU 6060 - RXD and dividing | 2017 Multi-University Training Contest 3

    /* HDU 6060 - RXD and dividing [ 分析,图论 ] | 2017 Multi-University Training Contest 3 题意: 给一个 n 个节点的树, ...

  4. HDU 6060:RXD and dividing(DFS)

    题目链接 题意 给出n个点,要把除1以外的点分成k个集合,然后对于每个集合要和1这个点一起求一个最小生成树,然后问这k个最小生成树的最大总和是多少. 思路 因为每个集合都包含1这个点,因此对于每个点都 ...

  5. 【构造+DFS】2017多校训练三 HDU 6060 RXD and dividing

    acm.hdu.edu.cn/showproblem.php?pid=6060 [题意] 给定一棵以1为根的树,把这颗树除1以外的结点划分为k个集合(可以有空集),把1加入划分后的集合 每个集合的结点 ...

  6. HDU 2874 Connections between cities(LCA)

    题目链接 Connections between cities LCA的模板题啦. #include <bits/stdc++.h> using namespace std; #defin ...

  7. HDU 6061 RXD and functions(NTT)

    题意 给定一个\(n​\) 次的 \(f​\) 函数,向右移动 \(m​\) 次得到 \(g​\) 函数,第 \(i​\) 次移动长度是 \(a_i​\) ,求 \(g​\) 函数解析式的各项系数,对 ...

  8. 2017 Multi-University Training Contest - Team 3 RXD and dividing(树)

    题解: 其实贪心地算就可以了 一个最优的分配就是每条边权贡献的值为min(k, sz[x]),sz[x]是指子树的大小 然后最后加起来就是答案. #include <iostream> # ...

  9. 洛谷P3379 【模板】最近公共祖先(LCA)

    P3379 [模板]最近公共祖先(LCA) 152通过 532提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 为什么还是超时.... 倍增怎么70!!题解好像有 ...

随机推荐

  1. vue清空input file

    input file是只读的,给form一个id,用form.reset()干掉里面input的值 document.getElementById("uploadForm")&am ...

  2. vue装逼神器简述

    主要是分享下用vuejs开发项目过程中遇到的问题,vuejs开发的优势和需要注意的地方. 项目主要页面:主页,最新,分类,分类列表,详情页,结果页,斗图(列表,制作页) 效果图: 地址:https:/ ...

  3. AGC025简要题解

    AGC025简要题解 B RGB Coloring 一道简单题,枚举即可. C Interval Game 考虑可以进行的操作只有两种,即左拉和右拉,连续进行两次相同的操作是没有用的. 左拉时肯定会选 ...

  4. document.onclick在ios上不触发的解决方法与touchstart点击穿透处理

    document.onclick = function (e) { var e = e ? e : window.event; var tar = e.srcElement || e.target; ...

  5. cuda中的二分查找

    使用背景 通常,在做高性能计算时,我们需要随机的连接某些点.这些点都具有自己的度量值,显然,度量值越大的值随机到的概率就会越大.因此,采用加权值得方法: void getdegreeSum(DG *g ...

  6. 寻找kernel32.dll的地址

    为了寻找kernel32.dll的地址,可以直接输出,也可以通过TEB,PEB等查找. 寻找TEB: dt _TEB nt!_TEB +0x000 NtTib : _NT_TIB +0x01c Env ...

  7. python 学习笔记 sqlalchemy

    数据库表是一个二维表,包含多行多列.把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含id和name的user表 ...

  8. defconfig file 的 位置

    Platform MSM8917 MSM8937 defconfig file position Android/kernel/msm-3.18/arch/arm/configs/

  9. VMware无法识别USB设备

    VMware虚拟机开始还能识别USB设备/U盘,突然就不行了,在网上找了好久,提供的方法大致如下: 1.   首先Ctrl+R启动运行,输入services.msc,找到一个VMware USB dr ...

  10. SQL 列 转换成 查询出来的 行

    查询  每个学生 的  (姓名,语文,数学,英语,成绩)为列 表结构如下: student: 学生表 grade 成绩表 : 查询出如下效果: SQL如下: select s.name,a.* fro ...