[poj1741]Tree

浅浅的花香味﹌ 2021-11-17 15:34 326阅读 0赞

点分治模板题,可以将同一棵树的链分为两种:1.通过重心;2.在子树内部。第2种可以搜下去,第1种的答案即$\sum_{i,j}[di+dj<=m]-\sum\limits_{i,j在同一个子树内}[di+dj<=m]$。

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 #include<cstdio>
  2. 2 #include<cstring>
  3. 3 #include<algorithm>
  4. 4 using namespace std;
  5. 5 #define N 10005
  6. 6 struct ji{
  7. 7 int nex,to,len;
  8. 8 }edge[N<<1];
  9. 9 int E,r,n,m,x,y,z,ans,a[N],head[N],vis[N],sz[N];
  10. 10 void add(int x,int y,int z){
  11. 11 edge[E].nex=head[x];
  12. 12 edge[E].to=y;
  13. 13 edge[E].len=z;
  14. 14 head[x]=E++;
  15. 15 }
  16. 16 void tot(int k,int fa,int sh){
  17. 17 a[++a[0]]=sh;
  18. 18 for(int i=head[k];i!=-1;i=edge[i].nex)
  19. 19 if ((!vis[edge[i].to])&&(edge[i].to!=fa))
  20. 20 tot(edge[i].to,k,sh+edge[i].len);
  21. 21 }
  22. 22 int calc(int k,int p){
  23. 23 int ans=a[0]=0;
  24. 24 tot(k,0,p);
  25. 25 sort(a+1,a+a[0]+1);
  26. 26 for(int i=1,j=a[0];i<j;i++){
  27. 27 while ((i<j)&&(a[i]+a[j]>m))j--;
  28. 28 ans+=j-i;
  29. 29 }
  30. 30 return ans;
  31. 31 }
  32. 32 void get(int k,int fa){
  33. 33 int ma=0;
  34. 34 sz[k]=1;
  35. 35 for(int i=head[k];i!=-1;i=edge[i].nex)
  36. 36 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
  37. 37 get(edge[i].to,k);
  38. 38 sz[k]+=sz[edge[i].to];
  39. 39 ma=max(ma,sz[edge[i].to]);
  40. 40 }
  41. 41 ma=max(ma,sz[0]-sz[k]);
  42. 42 if (ma<=sz[0]/2)r=k;
  43. 43 }
  44. 44 void dfs(int k){
  45. 45 ans+=calc(k,0);
  46. 46 vis[k]=1;
  47. 47 get(k,0);
  48. 48 for(int i=head[k];i!=-1;i=edge[i].nex)
  49. 49 if (!vis[edge[i].to]){
  50. 50 ans-=calc(edge[i].to,edge[i].len);
  51. 51 sz[0]=sz[edge[i].to];
  52. 52 get(edge[i].to,0);
  53. 53 dfs(r);
  54. 54 }
  55. 55 }
  56. 56 int main(){
  57. 57 while (scanf("%d%d",&n,&m)!=EOF){
  58. 58 if ((!n)&&(!m))return 0;
  59. 59 E=ans=0;
  60. 60 memset(head,-1,sizeof(head));
  61. 61 memset(vis,0,sizeof(vis));
  62. 62 for(int i=1;i<n;i++){
  63. 63 scanf("%d%d%d",&x,&y,&z);
  64. 64 add(x,y,z);
  65. 65 add(y,x,z);
  66. 66 }
  67. 67 sz[0]=n;
  68. 68 get(1,0);
  69. 69 dfs(r);
  70. 70 printf("%d\n",ans);
  71. 71 }
  72. 72 }

转载于:https://www.cnblogs.com/PYWBKTDA/p/11254676.html

发表评论

表情:
评论列表 (有 0 条评论,326人围观)

还没有评论,来说两句吧...

相关阅读

    相关 POJ--2255 Tree recovery

    补一下这一道恢复树的题目,前面好就做的吧。 题意:   就是给你一个前序遍历树和一个中序遍历树,让你恢复后序遍历树。([树的遍历][Link 1]) 解法: 利用了前序

    相关 [poj1741]Tree

    点分治模板题,可以将同一棵树的链分为两种:1.通过重心;2.在子树内部。第2种可以搜下去,第1种的答案即$\\sum\_\{i,j\}\[di+dj<=m\]-\\sum\\l

    相关 poj2054 Color a Tree

    神题。这题是巨毒瘤... 自己写真可谓是: 排空驭气奔如电,上天入地求之遍 上穷碧落下黄泉,两处茫茫皆不见 由于我们知道:不是树形时,不停选值最大的节点可以得到最小代价