HDU 6060 RXD and dividing(LCA)

Posted forever97‘s blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6060 RXD and dividing(LCA)相关的知识,希望对你有一定的参考价值。

 

【题目链接】 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)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 6060 RXD and dividing

HDU 6060 RXD and dividing(LCA)

HDU 6060 17多校3 RXD and dividing(树+dfs)

HDU 6065 RXD, tree and sequence (LCA DP)

hdu 6063 RXD and math

HDU 6065 RXD, tree and sequence (LCA+DP)