• POJ 1741 Tree (树分治入门)


    Tree
    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 8554   Accepted: 2545

    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. 

    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

    Source

    可以看论文。

    讲得很明白了。

    写分治主要是合并的过程。

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2013-11-17 14:30:29
      4 File Name     :E:2013ACM专题学习树的分治POJ1741.cpp
      5 ************************************************ */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 #include <time.h>
     19 using namespace std;
     20 const int MAXN = 10010;
     21 const int INF = 0x3f3f3f3f;
     22 struct Edge
     23 {
     24     int to,next,w;
     25 }edge[MAXN*2];
     26 int head[MAXN],tot;
     27 void init()
     28 {
     29     tot = 0;
     30     memset(head,-1,sizeof(head));
     31 }
     32 void addedge(int u,int v,int w)
     33 {
     34     edge[tot].to = v; edge[tot].w = w;
     35     edge[tot].next = head[u];head[u] = tot++;
     36 }
     37 bool vis[MAXN];
     38 int size[MAXN],dep[MAXN];
     39 int le,ri;
     40 int dfssize(int u,int pre)
     41 {
     42     size[u] = 1;
     43     for(int i = head[u];i != -1;i = edge[i].next)
     44     {
     45         int v = edge[i].to;
     46         if(v == pre || vis[v])continue;
     47         size[u] += dfssize(v,u);
     48     }
     49     return size[u];
     50 }
     51 int minn;
     52 //找重心
     53 void getroot(int u,int pre,int totnum,int &root)
     54 {
     55     int maxx = totnum - size[u];
     56     for(int i = head[u];i != -1;i = edge[i].next)
     57     {
     58         int v = edge[i].to;
     59         if(v == pre || vis[v])continue;
     60         getroot(v,u,totnum,root);
     61         maxx = max(maxx,size[v]);
     62     }
     63     if(maxx < minn){minn = maxx; root = u;}
     64 }
     65 void dfsdepth(int u,int pre,int d)
     66 {
     67     dep[ri++] = d;
     68     for(int i = head[u];i != -1;i = edge[i].next)
     69     {
     70         int v = edge[i].to;
     71         if(v == pre || vis[v])continue;
     72         dfsdepth(v,u,d+edge[i].w);
     73     }
     74 }
     75 int k;
     76 int getdep(int a,int b)
     77 {
     78     sort(dep+a,dep+b);
     79     int ret = 0, e = b-1;
     80     for(int i = a;i < b;i++)
     81     {
     82         if(dep[i] > k)break;
     83         while(e >= a && dep[e] + dep[i] > k)e--;
     84         ret += e - a + 1;
     85         if(e > i)ret--;
     86     }
     87     return ret>>1;
     88 }
     89 int solve(int u)
     90 {
     91     int totnum = dfssize(u,-1);
     92     int ret = 0;
     93     minn = INF;
     94     int root;
     95     getroot(u,-1,totnum,root);
     96     vis[root] = true;
     97     for(int i = head[root];i != -1;i = edge[i].next)
     98     {
     99         int v = edge[i].to;
    100         if(vis[v])continue;
    101         ret += solve(v); 
    102     }
    103     le = ri = 0;
    104     for(int i = head[root];i != -1;i = edge[i].next)
    105     {
    106         int v = edge[i].to;
    107         if(vis[v])continue;
    108         dfsdepth(v,root,edge[i].w);
    109         ret -= getdep(le,ri);
    110         le = ri;
    111     }
    112     ret += getdep(0,ri);
    113     for(int i = 0;i < ri;i++)
    114     {
    115         if(dep[i] <= k)ret++;
    116         else break;
    117     }
    118     vis[root] = false;
    119     return ret;
    120 }
    121 
    122 int main()
    123 {
    124     //freopen("in.txt","r",stdin);
    125     //freopen("out.txt","w",stdout);
    126     int n;
    127     int u,v,w;
    128     while(scanf("%d%d",&n,&k) == 2)
    129     {
    130         if(n == 0 && k == 0)break;
    131         init();
    132         for(int i = 1;i < n;i++)
    133         {
    134             scanf("%d%d%d",&u,&v,&w);
    135             addedge(u,v,w);
    136             addedge(v,u,w);
    137         }
    138         memset(vis,false,sizeof(vis));
    139         printf("%d
    ",solve(1));
    140     }
    141     return 0;
    142 }
  • 相关阅读:
    WPF基础之内容控件
    WPF基础之路由事件
    WPF基础分享之布局
    JMeter操作手册
    Jmeter安装和配置
    UI自动化--Web Driver小结
    对于自动化测试框架的总结
    UI自动化--selenium webdriver
    postman断言
    接口测试工具---postman的基本使用
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3454883.html
Copyright © 2020-2023  润新知