• 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=='
    '||ch=='
    '||ch=='	';
        }
        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
    ",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
    ",ans);
        }return 0;
    }
  • 相关阅读:
    Scala依赖注入
    Scala实现树形结构
    Spark GraphX快速入门
    mysql服务自启【Linux】
    Centos7安装mysql5.6
    Scala路径依赖【内部类】
    spark查看DF的partition数目及每个partition中的数据量【集群模式】
    Python自定义异常及抛出异常
    Spark应用【根据新df更新旧df】
    Linux安装JDK
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu6060.html
Copyright © 2020-2023  润新知