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

【DFS】BZOJ3522-[Poi2014]Hotel

时间:2016-11-12 13:41:28      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:amp   back   pre   print   printf   log   lld   class   span   

【题目大意】

给出一棵树,求三个节点使得它们两两之间的距离相等,问共有多少种可能性?

【思路】

显然,这三个节点是关于一个中心点对称地辐射出去的。

枚举中心点,往它的各个子树跑Dfs。tmp[i]表示当前子树深度为i的节点个数,p1[i]表示之前的子树中(不包括当前的子树),深度为i的节点的个数,p2[i]表示到当前子树之前,选取两个不同子树的节点的方案数。

对于当前这一棵子树的深度i,显然有ans+=tmp[i]*p2[i]。然后更新下次要用的p1[]、p2[],p2[i]+=p1[i]*tmp[i],p1[i]+=tmp[i]。

不要忘了long long。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int MAXN=5000+50;
 5 int n;
 6 int p1[MAXN],p2[MAXN],tmp[MAXN];
 7 vector<int> E[MAXN];
 8 
 9 void dfs(int fr,int u,int dep)
10 {
11     tmp[dep]++;
12     for (int i=0;i<E[u].size();i++)
13     {
14         int v=E[u][i];
15         if (v==fr) continue;
16         dfs(u,v,dep+1);
17     }
18 }
19 
20 void solve()
21 {
22     ll ans=0;
23     for (int i=1;i<=n;i++)
24     {
25         memset(p1,0,sizeof(p2));
26         memset(p2,0,sizeof(p1));
27         for (int j=0;j<E[i].size();j++)
28         {
29             memset(tmp,0,sizeof(tmp));
30             int to=E[i][j];
31             dfs(i,to,1);
32             for (int k=1;k<=n;k++)
33             {
34                 ans+=(ll)p2[k]*tmp[k];
35                 p2[k]+=p1[k]*tmp[k];
36                 p1[k]+=tmp[k];
37             }
38         }
39     }
40     printf("%lld\n",ans);
41 }
42 
43 void init()
44 {
45     scanf("%d",&n);
46     for (int i=0;i<n-1;i++)
47     {
48         int x,y;
49         scanf("%d%d",&x,&y);
50         E[x].push_back(y);
51         E[y].push_back(x);
52     }
53 }
54 
55 int main()
56 {
57     init();
58     solve();
59     return 0;    
60 } 

 

【DFS】BZOJ3522-[Poi2014]Hotel

标签:amp   back   pre   print   printf   log   lld   class   span   

原文地址:http://www.cnblogs.com/iiyiyi/p/6056374.html

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