zoukankan      html  css  js  c++  java
  • P3806 【模板】点分治1

    (color{#0066ff}{题目描述})

    给定一棵有n个点的树

    询问树上距离为k的点对是否存在。

    (color{#0066ff}{输入格式})

    n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径

    接下来m行每行询问一个K

    (color{#0066ff}{输出格式})

    对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)

    (color{#0066ff}{输入样例})

    2 1
    1 2 2
    2
    

    (color{#0066ff}{输出样例})

    AYE
    

    (color{#0066ff}{数据范围与提示})

    对于30%的数据n<=100

    对于60%的数据n<=1000,m<=50

    对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000

    (color{#0066ff}{题解})

    每次找重心,删去递归子树

    对于每个子树,dfs出到子树根(重心)的距离

    对于同一子树的,会有重复的路径,那不是答案,但是也统计了,所以在枚举孩子的时候要减回去,这部分答案在递归子树的时候会被统计

    每次把所有的子树的dis扔进数组里

    (O(n^2)收集答案)

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    LL in() {
    	char ch; int x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    struct node {
    	int to, dis;
    	node *nxt;
    	node(int to = 0, int dis = 0, node *nxt = NULL): to(to), dis(dis), nxt(nxt) {}
    	void *operator new (size_t) {
    		static node *S = NULL, *T = NULL;
    		return (S == T) && (T = (S = new node[1024]) + 1024), S++;
    	}
    };
    const int maxn = 2e5 + 10;
    int f[maxn], tmp[maxn], dis[maxn], siz[maxn], can[maxn];
    bool vis[maxn];
    node *head[maxn];
    int n, sum, m, root, num;
    
    void add(int from, int to, int dis) {
    	head[from] = new node(to, dis, head[from]);
    }
    void getdis(int x, int fa, int d) {
    	tmp[++num] = d;
    	dis[x] = d;
    	for(node *i = head[x]; i; i = i->nxt)
    		if(i->to != fa && !vis[i->to]) 
    			getdis(i->to, x, d + i->dis);
    }
    void calc(int x, int d, int flag) {
    	num = 0;
    	dis[x] = d;
    	getdis(x, 0, dis[x]);
    	for(int i = 1; i <= num; i++)
    		for(int j = 1; j <= num; j++)
    			if(i != j)
    				can[tmp[i] + tmp[j]] += flag;
    }
    void getroot(int x, int fa) {
    	siz[x] = 1;
    	f[x] = 0;
    	for(node *i = head[x]; i; i = i->nxt) {
    		if(i->to == fa || vis[i->to]) continue;
    		getroot(i->to, x);
    		siz[x] += siz[i->to];
    		f[x] = std::max(f[x], siz[i->to]);
    	}
    	f[x] = std::max(f[x], sum - siz[x]);
    	if(f[x] < f[root]) root = x;
    }
    
    void work(int x) {
    	calc(x, 0, 1);
    	vis[x] = true;
    	for(node *i = head[x]; i; i = i->nxt) 
    		if(!vis[i->to]) {
    			calc(i->to, i->dis, -1);
    			sum = siz[i->to];
    			root = 0;
    			getroot(i->to, 0);
    			work(root);
    		}
    }
    
    int main() {
    	n = in(), m = in();
    	int x, y, z;
    	for(int i = 1; i <= n - 1; i++) {
    		x = in(), y = in(), z = in();
    		add(x, y, z), add(y, x, z);
    	}
    	f[0] = n, sum = n;
    	getroot(1, 0), work(root);
    	while(m --> 0) printf(can[in()]? "AYE
    " : "NAY
    ");
    	return 0;
    }
    
  • 相关阅读:
    VR虚拟现实眼镜那些事
    C#使用MysqlBackup.Net 备份MySQL数据库
    AgileConfig服务端搭建
    IE浏览器,各版本的请求头信息
    搜索算法
    一个完整的信号采集系统项目开发流程
    Linux内核模块简介
    搭建wordpress开发环境
    AbstractRoutingDataSource+AOP+JNDI实现spring动态数据源
    Linux 挂载磁盘记录
  • 原文地址:https://www.cnblogs.com/olinr/p/10206208.html
Copyright © 2011-2022 走看看