• Tree,点分治


    Time Limit: 1 Sec  Memory Limit: 30 MB
    Submit: 13  Solved: 9
    [Submit][Status][Web Board]

    Description

    Give a tree with n vertices,each edge has a length(positive integer less than 1001). 
    Define dist(u,v)=The min distance between node u and v. 
    Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k. 
    Write a program that will count how many pairs which are valid for a given tree. 

    给定一个带权树N个结点(1<=N<=10000),定义dist(u,v)为u,v两个点间的最 
    短路径长度,路径长度定义为路径上所有边的权和。再给定一个K(1<=K<=10^9) 
    如果对于不同的两个结点a,b.如果满足dist(a,b)<=K,则称其为合法点对,求 
    有多少合法点对

    Input

    The input contains several test cases. 
    The first line of each test case contains two integers n, k. (n<=10000) 
    The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l. 
    The last test case is followed by two zeros. 

    Output

    For each test case output the answer on a single line. 

    Sample Input

    5 4
    1 2 3
    1 3 1
    1 4 2
    3 5 1
    0 0

    Sample Output

    8

    HINT

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;

    struct my{
        int next,v,w;
    };

    int read()
    {
        int p,data=0;
        char ch=0;
        while ((ch!='-') && ch<'0' || ch>'9') ch=getchar();
        if (ch=='-')
        {
            p=-1;
            ch=getchar();
        } else p=1;
        while (ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
        return data*p;
    }

    const int maxn=10000+10;

    my bian[maxn*2];
    int adj[maxn],fa,n,k,root=0,son[maxn],minn=(1<<30),dis[maxn*10],tot,sum;
    bool done[maxn];

    void myinsert(int u,int v,int w){
         bian[++fa].v=v;
         bian[fa].w=w;
         bian[fa].next=adj[u];
         adj[u]=fa;
    }

    void dfs(int x,int fa){
        int pp=0;
        son[x]=1;
        for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
            if(v==fa||done[v]) continue;
            dfs(v,x);
            son[x]+=son[v];
            pp=max(pp,son[v]);
        }
        pp=max(pp,sum-son[x]);//ÁíÍâÒ»´ó¿ÅÊ÷
        if(pp<minn) {
                minn=pp,root=x;
        }
    }

    void dfs2(int x,int d,int fa){
         dis[++tot]=d;
         for (int i=adj[x];i;i=bian[i].next){
                int v=bian[i].v;
            if(!done[v]&&v!=fa){
                dfs2(v,d+bian[i].w,x);
            }
         }
    }

    int calc(int x,int d){
        tot=0;
        int ans=0;
        dfs2(x,d,0);
        sort(dis+1,dis+1+tot);
        int i=1,j=tot;
        for (;i<j;i++){
            while(dis[i]+dis[j]>k && i<j) j--;
            ans+=j-i;
        }
        return ans;
    }

    int work(int x){
        minn=(1<<30);
        dfs(x,0);
        done[root]=true;
        int ans=0;
        ans+=calc(root,0);
        for (int i=adj[root];i;i=bian[i].next){
                int v=bian[i].v;
            if(done[v]) continue;
            sum=son[v];
            ans-=calc(v,bian[i].w);
            ans+=work(v);
        }
        return ans;
    }

    int main(){
        int u,v,w;
        while(scanf("%d%d",&n,&k)&&k+n){
                memset(bian,0,sizeof(bian));
                memset(adj,0,sizeof(adj));
                memset(done,false,sizeof(done));
                fa=0;
        for (int i=1;i<n;i++){
            u=read();
            v=read();
            w=read();
            myinsert(u,v,w);
            myinsert(v,u,w);
           }
           sum=n;
           printf("%d ",work(1));
        }
    return 0;
    }

  • 相关阅读:
    python基础之函数
    MySQL 安装 5.0
    MySQL安装 MySQL5.7.10免安装版配置,mysql5.7.10免安装版
    安装MYSql Windows7下MySQL5.5.20免安装版的配置
    网站集合
    andorid 开放工具集合
    Win7 x64 Eclipse无法识别手机 / adb interface有黄色感叹号,无法识别
    字符集 ISO-8859-1(3)
    字符集 ISO-8859-1(2)
    字符集 ISO-8859-1(1)
  • 原文地址:https://www.cnblogs.com/lmjer/p/9214403.html
Copyright © 2020-2023  润新知