poj 1741 洛谷 3806 【模板】点分治1 树的分治 点分治
来源:互联网 发布:55267网络电视直播 编辑:程序博客网 时间:2024/05/17 21:47
题目背景
感谢hzwer的点分治互测。
题目描述
给定一棵有n个点的树
询问树上距离为k的点对是否存在。
输入输出格式
输入格式:n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径
接下来m行每行询问一个K
输出格式:对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)
输入输出样例
输入样例#1:
2 11 2 22
输出样例#1:
AYE
https://www.luogu.org/problem/show?pid=3806#sub
#include <bits/stdc++.h>using namespace std;#define mo 100005#define mk make_pairvector< pair<int ,int > > d[mo];//箭头加空格int sz[mo];//树的重心..int sd[mo];//树的重心..int dist[mo];//计算到重心的距离int shux[mo];//标记点是从哪个子树下的bool de[10000005];//标记k是否出现过 int jl[mo];//删除树的重心标记int zz;void dfsz(int node,int dad,int &maxs,int &v,int n) //计算树的重心{ sz[node]=1; for(int i=0;i<d[node].size();i++) { int son=d[node][i].first; if(son!=dad&&!jl[son]) { dfsz(son,node,maxs,v,n); sz[node]+=sz[son]; if(sz[son]<maxs) { maxs=sz[son]; v=son; } } } if(n-sz[node]<maxs) { maxs=n-sz[node]; v=node; }}void dis(int node,int dad,int s,int &l,int j) //计算点到重心的距离{ dist[l]=s; shux[l]=j;//标记属于哪个子树 l++; if(dad==0) j=2; for(int i=0;i<d[node].size();i++) { int son=d[node][i].first; int ls=d[node][i].second; if(dad==0) j++;//只有dad为初始值的时候分子树编号 if(son!=dad&&!jl[son]) { dis(son,node,s+ls,l,j); } }}int shu(int k,int v,int d)//标记k是否出现过{ int l=0; memset(shux,0,sizeof(shux)); dis(v,0,d,l,0); for(int i=0;i<l;i++) { for(int j=i+1;j<l;j++) { if(shux[i]!=shux[j])//只有不同的子树可以相加 { //cout<<shux[i]<<' '<<shux[j]<<' '<<dist[i]<<' '<<dist[j]<<' '<<dist[i]+dist[j]<<' '<<i<<' '<<j<<endl; de[dist[i]+dist[j]]=1; } } } return 0;}void dx(int node,int dad,int &l)//计算树的大小{ l++; for(int i=0;i<d[node].size();i++) { int son=d[node][i].first; if(son!=dad&&!jl[son]) dx(son,node,l); }}void dfs(int x,int &ans,int k)//树的分治递归{ int n=0; dx(x,0,n);//首先判断大小 int mins=10000005,v=x; dfsz(x,0,mins,v,n);//之后机选树的重心 shu(k,v,0); //再去寻找距离重心的距离和距离为k 的数对 jl[v]=1; for(int i=0;i<d[v].size();i++) { int son=d[v][i].first; if(!jl[son]) { int le=d[v][i].second; //ans-=shu(k,son,le); dfs(son,ans,k); } } //jl[v]=0;}int main(){ int n,m,k; while(scanf("%d%d",&n,&m)!=EOF) { memset(de,false,sizeof(de)); int x,y,z; for(int i=1;i<n;i++) { //cin>>x>>y>>z; scanf("%d%d%d",&x,&y,&z); d[x].push_back(mk(y,z)); d[y].push_back(mk(x,z)); } int ans=0; dfs(1,ans,k); for(int i=0;i<m;i++) { //cin>>k; scanf("%d",&k); if(de[k]) //cout<<"AYE"<<endl; printf("AYE\n"); else //cout<<"NAY"<<endl; printf("NAY\n"); } }}
Tree
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 24713 Accepted: 8256
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.
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.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
5 41 2 31 3 11 4 23 5 10 0
Sample Output
8
Source
http://poj.org/problem?id=1741
#include <bits/stdc++.h>using namespace std;#define mo 100005#define mk make_pairvector< pair<int ,int > > d[mo];//箭头加空格int sz[mo];//树的重心..int sd[mo];//树的重心..int dist[mo];//距离重心的距离int jl[mo];//删重心的标记void dfsz(int node,int dad,int &maxs,int &v,int n) //寻找重心,n是计算树的大小得出{ sz[node]=1; for(int i=0;i<d[node].size();i++) { int son=d[node][i].first; if(son!=dad&&!jl[son]) { dfsz(son,node,maxs,v,n); sz[node]+=sz[son]; if(sz[son]<maxs) { maxs=sz[son]; v=son; } } } if(n-sz[node]<maxs) { maxs=n-sz[node]; v=node; }}void dis(int node,int dad,int s,int &l)//求其它点到重心的距离{ dist[l++]=s; for(int i=0;i<d[node].size();i++) { int son=d[node][i].first; int ls=d[node][i].second; if(son!=dad&&!jl[son]) dis(son,node,s+ls,l); }}int shu(int k,int v,int d)//数数有多少歌k对{ int l=0; dis(v,0,d,l); sort(dist,dist+l); int i=0,j=l-1; int ans=0; while(i<j) { while(dist[i]+dist[j]>k) j--; ans+=j-i; i++; } return ans;}void dx(int node,int dad,int &l)//计算树的大小,为了算树的重心{ l++; for(int i=0;i<d[node].size();i++) { int son=d[node][i].first; if(son!=dad&&!jl[son]) dx(son,node,l); }}void dfs(int x,int &ans,int k)//递归分治{ int n=0; dx(x,0,n);//首先确定树的大小。确定n的大小 int mins=10000005,v=x; dfsz(x,0,mins,v,n);//计算树的重心 ,将n带入 ans+=shu(k,v,0); //数多少个k jl[v]=1; for(int i=0;i<d[v].size();i++) { int son=d[v][i].first; if(!jl[son]) { int le=d[v][i].second; ans-=shu(k,son,le);//子树中重复的减去 dfs(son,ans,k); } }}int main(){ int n,k; while(cin>>n>>k&&n+k) { int x,y,z; for(int i=1;i<n;i++) { cin>>x>>y>>z; d[x].push_back(mk(y,z)); d[y].push_back(mk(x,z)); } int ans=0; dfs(1,ans,k); cout<<ans<<endl; }}
阅读全文
0 0
- poj 1741 洛谷 3806 【模板】点分治1 树的分治 点分治
- poj 1741 洛谷 3806 【模板】点分治1 树的分治 点分治
- POJ-1741 (点分治模板)
- 树分治(点分治模板)poj-1741 Tree
- 树分治(点分治模板)poj-1741 Tree
- 树分治(点分治模板)poj-1741 Tree
- POJ 1741 Tree, 树的重心, 树分治, 点分治
- POJ 1741 树的分治(点分治)入门
- POJ 1741 Tree 树的分治(点分治)
- 树的分治-点分治
- POJ 1741 点分治
- 【poj 1741】点分治
- POJ-1741 点分治
- POJ 1741 点分治
- poj 1741 点分治
- poj 1741 点分治
- 树分治-点分治
- 洛谷P3806 【模板】点分治1 【点分治】
- Spring Boot (五):与mybatis 的完美结合
- C++ 运算符重载
- codeforces875A Classroom Watch
- js,css模拟复选框
- java 接口
- poj 1741 洛谷 3806 【模板】点分治1 树的分治 点分治
- Spring Boot (六):发邮件
- iOS 11 vs 10: UI和交互全面对比分析
- JavaScript内置函数
- 阿里官方Java代码规范标准《阿里巴巴Java开发手册 终极版 v1.3.0》
- pycharm第一次使用
- 逆波兰表达式
- mysql 索引详解
- java多线程:消息队列