• poj 1741 Tree


      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

      题目大意讲的是给定一棵带边权的树,求有多少对点,之间的距离不超过给定的k。

      树分治的经典例题。我用的点分,每次用遍历去找重心(降低时间复杂度,防止退化成链,导致时间复杂度变为$O(n^{2})$),然后计算经过重心的链的条数,然后“删掉”重心,递归剩下的子树。

      至于如何快速地处理经过重心的链的条数,主要有两种方法

    1. 遍历得到所有点距离重心的距离,然后用所有路径,减去在同一子树内的路径。
      置于这个怎么快速计算,有个方法:
      ①对所有距离排个序,然后从左到右枚举i,因为距离是从小到大的,它们的总和又不超过k,那么最大的deps[j]和deps[i]的和不超过k的j一定是递减的,所以可以实现O(n)来计算。
      ②如果j > i那么就给数量加上(j - i)(i不能自己到自己,所以有j - i个点到它的距离满足条件),否则就可以break了。
      用这个方法先处理重心的子树,然后再处理当前子树,就可以得到当前这一层的答案。总时间复杂度$Oleft(nlog^{2} n ight)$。当然也可以做到nlogn,只是我不会而已。
    2. 用值域线段树(动态开节点,不然我就用树状数组了),维护已经处理完的子树中的点到重心的距离对应的方案数。然后对于正在处理的子树,遍历它,算出一个点到重心的距离,然后就在值域线段树里查询(你知道该查什么)。处理完了就用子树中的数据去更新线段树。累加起来就是当前层的答案。当然写完点分你还想写带动态开节点的值域线段树吗?虽然总时间复杂度差不多,也是$Oleft(nlog^{2} n ight)$(算错了别怪我)

      求树的重心,不懂就看一下这里:指定一个节点作为“根”,一次dfs得到每个节点及其子树的大小。然后for,它上面的节点数就用总结点数减去size[node],按照定义求重心就行了。

    Code(极其不简洁的代码)

      1 /**
      2  * poj.org
      3  * Problem#1741
      4  * Accepted
      5  * Time:172ms
      6  * Memory:1476k
      7  */
      8 #include<iostream>
      9 #include<fstream>
     10 #include<sstream>
     11 #include<cstdio>
     12 #include<cstdlib>
     13 #include<cstring>
     14 #include<ctime>
     15 #include<cctype>
     16 #include<cmath>
     17 #include<algorithm>
     18 #include<stack>
     19 #include<queue>
     20 #include<set>
     21 #include<map>
     22 #include<vector>
     23 #ifndef WIN32
     24 #define AUTO "%lld"
     25 #else
     26 #define AUTO "%I64d"
     27 #endif
     28 using namespace std;
     29 typedef bool boolean;
     30 #define inf 0xfffffff
     31 #define smin(a, b)    (a) = min((a), (b))
     32 #define smax(a, b)    (a) = max((a), (b))
     33 template<typename T>
     34 inline void readInteger(T& u){
     35     char x;
     36     int aFlag = 1;
     37     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     38     if(x == -1)    return;
     39     if(x == '-'){
     40         x = getchar();
     41         aFlag = -1;
     42     }
     43     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
     44     ungetc(x, stdin);
     45     u *= aFlag;
     46 }
     47 
     48 ///map template starts
     49 typedef class Edge{
     50     public:
     51         int end;
     52         int next;
     53         int w;
     54         Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w){}
     55 }Edge;
     56 typedef class MapManager{
     57     public:
     58         int ce;
     59         int *h;
     60         Edge *edge;
     61         MapManager(){}
     62         MapManager(int points, int limit):ce(0){
     63             h = new int[(const int)(points + 1)];
     64             edge = new Edge[(const int)(limit + 1)];
     65             memset(h, 0, sizeof(int) * (points + 1));
     66         }
     67         inline void addEdge(int from, int end, int w){
     68             edge[++ce] = Edge(end, h[from], w);
     69             h[from] = ce;
     70         }
     71         inline void addDoubleEdge(int from, int end, int w){
     72             addEdge(from, end, w);
     73             addEdge(end, from, w);
     74         }
     75         Edge& operator [](int pos) {
     76             return edge[pos];
     77         }
     78         inline void clear() {
     79             delete[] h;
     80             delete[] edge;
     81             ce = 0;
     82         }
     83 }MapManager;
     84 #define m_begin(g, i) (g).h[(i)]
     85 ///map template ends
     86 
     87 int n, k;
     88 MapManager g;
     89 int* size;            //大小 
     90 boolean* visited;    //是否做过重心 
     91 
     92 inline boolean init() {
     93     readInteger(n);
     94     readInteger(k);
     95     if(n == 0 && k == 0)    return false;
     96     g = MapManager(n, 2 * n);
     97     size = new int[(const int)(n + 1)];
     98     visited = new boolean[(const int)(n + 1)];
     99     memset(visited, false, sizeof(boolean) * (n + 1));
    100     for(int i = 1, a, b, c; i < n; i++) {
    101         readInteger(a);
    102         readInteger(b);
    103         readInteger(c);
    104         g.addDoubleEdge(a, b, c);
    105     }
    106     return true;
    107 }
    108 
    109 void getSize(int node, int fa){            //计算大小 
    110     size[node] = 1;
    111     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
    112         int &e = g[i].end;
    113         if(e == fa || visited[e])    continue;
    114         getSize(e, node);
    115         size[node] += size[e];
    116     }
    117 }
    118 
    119 void getG(int node, int fa, int& G, int& minv, int all) { //得到重心 
    120     int c = all - size[node];
    121     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
    122         int& e = g[i].end;
    123         if(e == fa || visited[e])    continue;
    124         smax(c, size[e]);
    125         getG(e, node, G, minv, all);
    126     }
    127     if(c < minv)    G = node, minv = c;
    128 }
    129 
    130 int top;
    131 int* dep;            //到当前重心的距离 
    132 void getDeps(int node, int fa, int d) {        //求距离 
    133     dep[++top] = d;
    134     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
    135         int &e = g[i].end;
    136         if(e == fa || visited[e])    continue;
    137         getDeps(e, node, d + g[i].w);
    138     }
    139 }
    140 
    141 int calcCount(int* deps, int from, int end) {    //计算数量 
    142     if(from >= end)    return 0;
    143     int ret = 0;
    144     sort(deps + from, deps + end + 1);
    145     int r = end;
    146     for(int i = from; i <= end; i++) {
    147         while(deps[i] + deps[r] > k && r > i)    r--;
    148         if(r == i)    return ret;
    149         ret += r - i;
    150     }
    151     return ret;
    152 }
    153 
    154 long long res;
    155 void work(int node) {                //点分治主过程 
    156     int G, minv = inf;
    157     getSize(node, 0);
    158     if(size[node] == 1)    return;
    159     getG(node, 0, G, minv, size[node]);
    160     top = 1;
    161     int b = 1;
    162     dep[1] = 0;
    163     for(int i = m_begin(g, G); i != 0; i = g[i].next) {
    164         int& e = g[i].end;
    165         if(visited[e])    continue;
    166         getDeps(e, G, g[i].w);
    167         res -= calcCount(dep, b + 1, top);
    168         b = top; 
    169     }
    170     visited[G] = true;
    171     res += calcCount(dep, 1, top);
    172     for(int i = m_begin(g, G); i != 0; i = g[i].next) {
    173         int& e = g[i].end;
    174         if(visited[e])    continue;
    175         work(e);
    176     }
    177 }
    178 
    179 inline void solve() {
    180     res = 0;
    181     dep = new int[(const int)(n + 1)];
    182     work(1);
    183     printf(AUTO"
    ", res);
    184     delete[] dep;
    185     delete[] size;
    186     delete[] visited;
    187     g.clear();
    188 }
    189 
    190 int main() {
    191     while(init()) {
    192         solve();
    193     }
    194     return 0;
    195 }
  • 相关阅读:
    SQL SERVER NVARCHAR字段INSERT 中文乱码问题解决
    解析$(this).data('type');
    使用HttpWebRequest发送自定义POST请求
    C#使用WebClient下载文件到本地目录
    linux开发时,想用的链接暂存
    程序进行重定位的技术按重定位的时机分类
    文件分类
    快表、页表
    操作系统的发展与分类
    网络操作系统和分布式操作系统的区别
  • 原文地址:https://www.cnblogs.com/yyf0309/p/6592110.html
Copyright © 2020-2023  润新知