zoukankan      html  css  js  c++  java
  • [BZOJ1468]Tree

    [BZOJ1468]Tree

    试题描述

    给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

    输入

    N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

    输出

    一行,有多少对点之间的距离小于等于k

    输入示例

    7
    1 6 13
    6 3 9
    3 5 7
    4 1 3
    2 4 20
    4 7 2
    10

    输出示例

    5

    数据规模及约定

    见“输入

    题解

    又来一道裸点分治,分别统计重心下面每一颗子树的路径长度和整棵树的路径长度,二分一下算方案数,去重。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
    
    #define maxn 40010
    #define maxm 80010
    int n, m, K, head[maxn], next[maxm], to[maxm], dist[maxm], ans;
    
    void AddEdge(int a, int b, int c) {
    	to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
    	swap(a, b);
    	to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
    	return ;
    }
    
    bool vis[maxn];
    int root, size, f[maxn], siz[maxn];
    void getroot(int u, int fa) {
    	siz[u] = 1; f[u] = 0;
    	for(int e = head[u]; e; e = next[e]) if(!vis[to[e]] && to[e] != fa) {
    		getroot(to[e], u);
    		siz[u] += siz[to[e]];
    		f[u] = max(f[u], siz[to[e]]);
    	}
    	f[u] = max(f[u], size - siz[u]);
    	if(f[root] > f[u]) root = u;
    	return ;
    }
    int A[maxn], tot, B[maxn], ToT;
    void dfs(int u, int fa, int d) {
    	if(d > K) return ;
    	A[++tot] = d;
    	for(int e = head[u]; e; e = next[e]) if(!vis[to[e]] && to[e] != fa)
    		dfs(to[e], u, d + dist[e]);
    	return ;
    }
    void solve(int u) {
    //	printf("u: %d
    ", u);
    	vis[u] = 1;
    	ToT = 0;
    	int sum = 0;
    	for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) {
    		tot = 0;
    		dfs(to[e], u, dist[e]);
    		sort(A + 1, A + tot + 1);
    		ans += tot;
    //		for(int i = 1; i <= tot; i++) printf("%d ", A[i]); putchar('
    ');
    		for(int i = 1; i <= tot; i++) {
    			int k = upper_bound(A + 1, A + tot + 1, K - A[i]) - A - 1;
    			sum += k;
    //			printf("%d ", k);
    		}
    //		puts("end");
    		for(int i = 1; i <= tot; i++) B[++ToT] = A[i];
    	}
    //	printf("here: %d ", sum);
    	int tmp = 0;
    	sort(B + 1, B + ToT + 1);
    	for(int i = 1; i <= ToT; i++) {
    		int k = upper_bound(B + 1, B + ToT + 1, K - B[i]) - B - 1;
    		tmp += k;
    	}
    //	printf("%d
    ", tmp);
    	ans += (tmp - sum >> 1);
    	for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) {
    		root = 0; f[0] = n + 1; size = siz[u]; getroot(to[e], u);
    		solve(root);
    	}
    	return ;
    }
    
    int main() {
    	n = read();
    	for(int i = 1; i < n; i++) {
    		int a = read(), b = read(), c = read();
    		AddEdge(a, b, c);
    	}
    	K = read();
    	
    	root = 0; f[0] = n + 1; size = n; getroot(1, 0);
    	solve(root);
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    【Django】Django REST Framework简单教程
    【SpringBoot | Druid】SpringBoot整合Druid
    【SpringBoot | Swagger】SpringBoot整合Swagger
    【Vue | ElementUI】Vue离开当前页面时弹出确认框实现
    【SpringBoot | Redis】SpringBoot整合Redis
    【评测机】评测时报错cc1plus: fatal error: /xx/xx/main.cpp: Permission denied compilation terminated.的解决方法
    Hello world!
    【续】将HUSTOJ备份数据并迁移至Ubuntu16.04
    将HUSTOJ备份数据并迁移至Ubuntu16.04
    【BZOJ2118】墨墨的等式【循环节做法】
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5907077.html
Copyright © 2011-2022 走看看