zoukankan      html  css  js  c++  java
  • 洛谷 P4178 Tree

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define rg register
    #define _ 40010
    using namespace std;
    int n,record[_],num_of_edges,size[_],dfn[_],dfns,F[_],root,dis[_];//size[]不多说,F[]是i点儿子中最大子树大小
    bool passed[_];
    int stack[_],top,ans,k;
    struct pp
    {
        int next,to,w;
    }edge[_<<1];
    inline int read()
    {
        rg int save=0,w=1;rg char q=getchar();
        while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
        while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
        return save*w;
    }
    void getroot(rg int i,rg int fa,rg int s)
    {
        size[i]=1,F[i]=0,dfn[i]=++dfns;
        for(rg int j=record[i];j;j=edge[j].next)
        {
            rg int to=edge[j].to;
            if(to!=fa&&!passed[to])
            {
                getroot(to,i,s);
                F[i]=max(F[i],size[to]);
                size[i]+=size[to];
            }
        }
        F[i]=max(F[i],s-size[i]);
        root=F[i]<F[root]?i:root;
    }
    void comput(rg int i,rg int dad)
    {
        stack[++top]=dis[i];//stack直接把边权记下来,无需记点
        for(rg int j=record[i];j;j=edge[j].next)
        {
            rg int to=edge[j].to;
            if((!passed[to])&&dad!=to)
            {
                dis[to]=dis[i]+edge[j].w;
                comput(to,i);
            }
        }
    }
    inline int doit(rg int i,rg int d)//数出 该联通块中若使所有路径强制经过重心,<=k的有多少    (d为初始距离(去重用))
    {
        top=0;dis[i]=d;
        comput(i,0);//计算各点到该重心的路径长
        sort(stack+1,stack+top+1);
        rg int l=1,r=top,result=0;
        while(l<r)
            if(stack[l]+stack[r]<=k)result+=r-l,l++;
            else r--;
        return result;
    }
    void dfs(rg int i,rg int all)
    {
        ans+=doit(i,0);
        passed[i]=1;
        for(rg int j=record[i];j;j=edge[j].next)
        {
            rg int to=edge[j].to;
            if(!passed[to])
            {
                rg int s;
    /* ☆☆☆*/    ans-=doit(to,edge[j].w);//去掉那些 在to的子树加上了[i->to的边权]被算作i的贡献的路径(这些路径本不存在)
                if(dfn[i]<dfn[to])s=size[to];
                else s=all-size[i];
                root=0;dfns=0;
                getroot(to,i,s);
    //            printf("%d
    ",root);
                dfs(to,s);
            }
        }
    }
    inline void add(rg int from,rg int to,rg int ww)
    {
        edge[++num_of_edges]=(pp){record[from],to,ww};
        record[from]=num_of_edges;
    }
    int main()
    {
        n=read();
    //    cout<<"___
    "<<n<<endl;
        rg int i,j;
        for(i=1;i<n;++i)
        {
            rg int x=read(),y=read(),ww=read();
            add(x,y,ww),add(y,x,ww);
    //        cout<<x<<' '<<y<<' '<<ww<<endl;
        }
        k=read();
    //    cout<<k<<endl;
        root=0;F[0]=n;//操作 "root=F[i]<F[root]?i:root" 需要
        getroot(1,0,n);
        dfs(root,n);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    pymongo
    活动专题,各种手机的适配
    怎么判断是qq浏览器还是uc浏览器?
    并的用法,存在并执行~~
    window.location.href在微信端不起作用的解决方法?
    div双击全屏,再双击恢复到原来的状态vue,js来做
    avalon结合原生js tab切换
    vue指令大全~~~
    jquery中$.get()如何让跨域请求携带cookie?
    git 的使用方法以及要注意的地方~/git stash的使用
  • 原文地址:https://www.cnblogs.com/c-wen/p/9337803.html
Copyright © 2011-2022 走看看