树上点分治学习记录

跟着机房的潮流学了点分治,发现这个东西其实还蛮好写的,学会思想,很容易YY出来。直接上习题。

POJ 1741 TREE

点分治的模板题,首先设点x到当前子树跟root的距离为gx,则满足gx+gy≤k可以加进答案,但是注意如果x,y在同一棵子树中,就要删去对答案的贡献,以为x,y会在其所在的子树中在计算一次。注意无根树转有根树的过程,需要选取树的重心防止复杂度从O(nlog2n)退化为O(n2) code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 100000
using namespace std;
struct hp{
    int u,v,w;
}a[20001];
struct hq{
    int size;
}tree[10001];
bool done[10001];
int point[10001],next[20001];
int len[10001];
int n,m,e=0,t=0;
int size,root,sizenow,tot,ans=0;
void add(int u,int v,int w)
{
    e++; a[e].u=u; a[e].v=v; a[e].w=w; next[e]=point[u]; point[u]=e;
    e++; a[e].u=v; a[e].v=u; a[e].w=w; next[e]=point[v]; point[v]=e;
}
void findsize(int now,int last)
{
    int i,tmp=0;
    sizenow++;
    for (i=point[now];i;i=next[i])
      if (a[i].v!=last&&!done[a[i].v])
        findsize(a[i].v,now);
}
void findroot(int now,int last)
{
    int i,tmp=0;
    tree[now].size=1; tmp=0;
    for (i=point[now];i;i=next[i])
      if (a[i].v!=last&&!done[a[i].v])
        {
          findroot(a[i].v,now);
          tree[now].size+=tree[a[i].v].size;
          if (tree[a[i].v].size>tmp)
            tmp=tree[a[i].v].size;
        }
    if (sizenow-tree[now].size>tmp) tmp=sizenow-tree[now].size;
    if (tmp<size)
      {root=now; size=tmp;}
}
void findroad(int now,int last,int road)
{
    int i,tmp=0;
    len[++t]=road;
    if (road>m) return;
    for (i=point[now];i;i=next[i])
      if (a[i].v!=last&&!done[a[i].v])
        findroad(a[i].v,now,road+a[i].w);
}
int calc(int k)
{
    int i,l,r,ret=0;
    sort(len+1,len+t+1);
    for (l=1,r=t;l<r;)
      {
        if (len[l]+len[r]<=k) ret+=r-l++;
        else r--;
      }
    return ret;
}
void work(int now)
{
    int i;
    sizenow=0; t=0;  size=inf;
    findsize(now,0);
    findroot(now,0);
    findroad(root,0,0);
    done[root]=true;
    ans+=calc(m);
    for (i=point[root];i;i=next[i])
      if (!done[a[i].v])
        {
          t=0; sizenow=0; size=inf;
          findroad(a[i].v,0,0);
          ans-=calc(m-2*a[i].w);
          findsize(a[i].v,0);
          findroot(a[i].v,0);
          work(a[i].v);
        }
}
int main()
{
    int i,x,y,z;
    scanf("%d%d",&n,&m);
    while (n!=0&&m!=0)
      {
        e=0; ans=0;
        memset(point,0,sizeof(point));
        memset(done,false,sizeof(done));
        for (i=1;i<=n-1;++i)
         {
           scanf("%d%d%d",&x,&y,&z);
           add(x,y,z);
         }
        work(1);
        printf("%d\n",ans);
        scanf("%d%d",&n,&m);
      }
}
时间: 2024-10-10 20:54:10

树上点分治学习记录的相关文章

Python学习记录-2016-12-17

今日学习记录 模块: import os#导入os模块 import sys#导入sys模块 os.system("df -h")#执行df -h命令 cmd_res = os.popen("df -h").read()#将命令的返回结果赋值给cmd_res,如果不加入.read()会显示命令的返回加过在内存的位置 print(sys.path)#显示系统变量路径,一般个人模块位于site-packages下,系统模块位于lib下 print(sys.argu[2]

Objc基础学习记录5

NSMutableString类继承的NSString类. NSMutableString是动态的字符串. 1.appendingString 方式: 向字符串尾部添加一个字符串. 2.appendingFormat:可以添加多个类型的字符串. int,chat float,double等 3.stringWithString 创建字符串, 4.rangeOfString 返回str1在另一个字符串中的位置. 5.NSMakeRange(0,3) 字符串0位到3位. 6.deleteCharac

Windows API 编程学习记录&lt;二&gt;

恩,开始写Windows API编程第二节吧. 上次介绍了几个关于Windows API编程最基本的概念,但是如果只是看这些概念,估计还是对Windows API不是很了解.这节我们就使用Windows API 让大家来了解下Windows API的用法. 第一个介绍的Windows API 当然是最经典的MessageBox,这个API 的作用就是在电脑上显示一个对话框,我们先来看看这个API的定义吧: int WINAPI MessageBox(HWND hWnd, LPCTSTR lpTe

Windows API 编程学习记录&lt;三&gt;

恩,开始写API编程的第三节,其实马上要考试了,但是不把这节写完,心里总感觉不舒服啊.写完赶紧去复习啊       在前两节中,我们介绍了Windows API 编程的一些基本概念和一个最基本API函数 MessageBox的使用,在这节中,我们就来正式编写一个Windows的窗口程序. 在具体编写代码之前,我们必须先要了解一下API 编写窗口程序具体的三个基本步骤:             1. 注册窗口类:             2.创建窗口:             3.显示窗口: 恩,

Python学习记录day6

Python学习记录day6 学习 python Python学习记录day6 1.反射 2.常用模块 2.1 sys 2.2 os 2.3 hashlib 2.3 re 1.反射 反射:利用字符串的形式去对象(默认)中操作(寻找)成员 cat commons.py #!/usr/bin/env python#_*_coding:utf-8_*_''' * Created on 2016/12/3 21:54. * @author: Chinge_Yang.''' def login(): pr

Python学习记录-2016-11-29

今日学习记录: 心灵鸡汤: 要有合适自己的目标,一个目标一个目标实现,切忌好高骛远: 最好的投资就是投资自己: 实现梦想 学习,学习,再学习: Talk is cheap. 从本身而言,余三十而立之年,从事测试行业7七年有余,一年半华为外包路由器,两年无线wifi测试,一年半网管软件测试,一年自动化测试经理,推行公司自动化测试进程,从开始的TCL,到现在的python,工欲善其事必先利其器,所以自己来学习,总体我认为我的目标是一直前进的,不断变化的,但是方向并没有大的错误,有些累,所以近期有些懈

程序的机械级表示学习记录

程序的机械级表示学习记录 X86的三代寻址方式 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全. 8086的分段模式. IA32的带保护模式的平坦模式. 对于机械级编程的两种重要抽象 ISA:机械级程序的格式和行为,定义为指令集体系结构,它定义了处理器状态.指令的格式,以及每条指令对状态的影响. 虚拟地址:机器级程序使用的存储器地址,提供的存储器模型看上去是一个非常大的数组.存储器系统的实际实现是将多个硬件存储器和操作系统软件组合起来的. 在GCC中获得汇编代码与反汇编 获得汇编代码:

poj2114 寻找树上存在长度为k点对,树上的分治

寻找树上存在长度为k点对,树上的分治  代码和  这个  差不多 ,改一下判断的就好 #include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; const int maxn=10004; int H[maxn],nx[maxn*2],to[maxn*2],numofE,d

python 系统地学习记录

由头: python值得一学. 尝试一下写学习记录,看看效果. 1.记录一些不熟悉或者重要的知识点. 2.记录一些遇到的问题,标签 Question. 书:python基础教程(第2版) Chapter 1:基础知识 本章的内容熟悉即可. 比较重要的是字符串,单双引号转义,str,repr... Time 1.5 h  2015.8.31 23:09 版权声明:本文为博主原创文章,未经博主允许不得转载.