码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 6060 RXD and dividing(LCA)

时间:2017-08-04 17:13:37      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:--   printf   algo   vector   覆盖   tor   int   inline   names   

 

【题目链接】 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)

标签:--   printf   algo   vector   覆盖   tor   int   inline   names   

原文地址:http://www.cnblogs.com/forever97/p/hdu6060.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!