码迷,mamicode.com
首页 > 编程语言 > 详细

C++之路进阶——点分(tree)

时间:2016-01-19 07:59:25      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

技术分享
F.A.QsHomeDiscussProblemSetStatusRanklistContestModifyUser   gryz2016Logout捐赠本站
Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入、输出语句及数据类型及范围,避免无谓的RE出现。

1468: Tree

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 774  Solved: 412
[Submit][Status][Discuss]

Description

给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

Input

N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

Output

一行,有多少对点之间的距离小于等于k

Sample Input

7
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10

Sample Output

5

HINT

题解:

    点分。。。

代码:

    

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define maxn  400100
 5 
 6 using namespace std;
 7 
 8 int n,m,root,sum,ans,cnt,head[maxn],son[maxn],f[maxn],vis[maxn],deep[maxn],d[maxn];
 9 
10 struct ss
11    {
12         int to;
13         int next;
14         int w;
15    }e[maxn];
16    
17 void insert(int u,int v,int w)
18    {
19        e[++cnt].to=v; e[cnt].next=head[u]; e[cnt].w=w; head[u]=cnt;
20        e[++cnt].to=u; e[cnt].next=head[v]; e[cnt].w=w; head[v]=cnt;
21    }
22    
23 void getroot(int x,int fa) 
24    {
25         son[x]=1;
26         f[x]=0;
27         for (int i=head[x];i;i=e[i].next)
28           if (!vis[e[i].to]&&e[i].to!=fa)
29              {
30                   getroot(e[i].to,x);
31                   son[x]+=son[e[i].to];
32                   f[x]=max(f[x],son[e[i].to]);
33              }
34       f[x]=max(f[x],sum-son[x]);
35       if (f[x]<f[root]) root=x;         
36      } 
37 
38 void getdeep(int x,int fa)
39      {
40          deep[++deep[0]]=d[x];
41          for (int i=head[x];i;i=e[i].next)
42              if (!vis[e[i].to]&&e[i].to!=fa)
43                  {
44                    d[e[i].to]=d[x]+e[i].w;    
45                    getdeep(e[i].to,x);     
46                  }
47            }
48     
49 int cal(int x,int now)
50     {
51       d[x]=now;    
52       deep[0]=0;    
53       getdeep(x,0);
54       sort(deep+1,deep+deep[0]+1);
55       int t=0,l,r;
56       for(l=1,r=deep[0];l<r;)
57        {
58         if(deep[l]+deep[r]<=m){t+=r-l;l++;}
59         else r--;
60        }
61     return t;
62     }
63     
64 void work(int x)
65     {
66      ans+=cal(x,0); 
67      vis[x]=1;    
68      for (int i=head[x];i;i=e[i].next)    
69        if(!vis[e[i].to]) 
70          {
71            ans-=cal(e[i].to,e[i].w);    
72            sum=son[e[i].to];
73            root=0;
74            getroot(e[i].to,root);
75            work(root);    
76           } 
77     }
78 
79 int main()
80    {
81       scanf("%d",&n);    
82          for (int i=1;i<n;i++)
83            {
84               int u,v,w;    
85               scanf("%d%d%d",&u,&v,&w);    
86               insert(u,v,w);
87            }
88       scanf("%d",&m);       
89        sum=n;
90        f[0]=0x7fffffff;
91        getroot(1,0);
92        work(1);
93        printf("%d",ans);
94    }                         

 

C++之路进阶——点分(tree)

标签:

原文地址:http://www.cnblogs.com/grhyxzc/p/5141007.html

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