【题目链接】 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. [bzoj4569][SCOI2016]萌萌哒-并查集+倍增

    Brief Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条 件表示为四个数,l1,r1,l2,r2,即两 ...

  2. bzoj 2434 fail tree+dfs序

    首先比较明显的是我们可以将字符串组建立ac自动机,那么对于询问s1字符串在s2字符串中出现的次数,就是在以s1结尾为根的fail tree中,子树有多少个节点是s2的节点,这样我们处理fail tre ...

  3. jq_从右向右的滑入滑出效果

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. web-project 故障查看功能 检测是否启动fmd服务

    def check_fmd_service(): try: output = subprocess.check_output('svcs -H -o state fmd',shell=True) st ...

  5. bootstrap-table设置某列序号自增

    col = [{ field: 'SerialNumber', title: '序号', formatter: function (value, row, index) { return index+ ...

  6. Tabular DataStream protocol 协议

    Tabular DataStream protocol 协议 Freetds 创建过程 https://wenku.baidu.com/view/2076cbfaaef8941ea76e0576.ht ...

  7. ios IAP 内购验证

    参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购 ...

  8. 使用 Visual Studio 部署 .NET Core 应用 ——.Net Core 部署到SUSE Linux Enterprise Server 12 SP2 64 位(GNOME 版本3.20.2)

    SUSE Linux安装 apache 命令:sudo zypper in apache 设置apache 服务可用 命令:sudo systemctl enable apache2.service启 ...

  9. leetcode 之Plus One(9)

    这题需要注意的是最后的进位 vector<int> plusOne(vector<int>& nums,int num) { add(nums, num); } voi ...

  10. Nginx惊群处理

    惊群:是指在多线程/多进程中,当有一个客户端发生链接请求时,多线程/多进程都被唤醒,然后只仅仅有一个进程/线程处理成功,其他进程/线程还是回到睡眠状态,这种现象就是惊群. 惊群是经常发生现在serve ...