bzoj 1316: 树上的询问 (点分治)
来源:互联网 发布:王千源事件 知乎 编辑:程序博客网 时间:2024/05/18 11:07
1316: 树上的询问
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 564 Solved: 150
[Submit][Status][Discuss]
Description
一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No.
Input
第一行两个整数n, p分别表示点的个数和询问的个数. 接下来n-1行每行三个数x, y, c,表示有一条树边x→y,长度为c. 接下来p行每行一个数Len,表示询问树中是否存在一条长度为Len的路径.
Output
输出有p行,Yes或No.
Sample Input
6 4
1 2 5
1 3 7
1 4 1
3 5 2
3 6 3
1
8
13
14
1 2 5
1 3 7
1 4 1
3 5 2
3 6 3
1
8
13
14
Sample Output
Yes
Yes
No
Yes
Yes
No
Yes
HINT
30%的数据,n≤100.
100%的数据,n≤10000,p≤100,长度≤1000000.
做完此题可看下POJ 3237 Tree
Source
题解:点分治
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define N 30003 using namespace std; int n,m,tot,num[10000003]; int point[N],next[N],v[N],len[N],cnt,root,sum,vis[N]; int f[N],deep[N],mp[N],d[N],ak[N],mark[N],son[N],g[N]; void add(int x,int y,int z) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; len[tot]=z; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; len[tot]=z; //cout<<x<<" "<<y<<" "<<z<<endl; } void getroot(int x,int fa) { son[x]=1; f[x]=0; for (int i=point[x];i;i=next[i]){ if (vis[v[i]]||v[i]==fa) continue; getroot(v[i],x); son[x]+=son[v[i]]; f[x]=max(f[x],son[v[i]]); } f[x]=max(f[x],sum-son[x]); if (f[x]<f[root]) root=x; } void getdeep(int x,int fa) { deep[++deep[0]]=d[x]; for (int i=point[x];i;i=next[i]){ if (vis[v[i]]||v[i]==fa) continue; d[v[i]]=d[x]+len[i]; getdeep(v[i],x); } } void cal(int x,int now,int opt) { d[x]=now; deep[0]=0; getdeep(x,0); sort(deep+1,deep+deep[0]+1); g[0]=0; for (int i=1;i<=deep[0];i++) if (deep[i]!=deep[i-1]||i==1) g[++g[0]]=deep[i],num[g[0]]=1; else num[g[0]]++; for (int i=1;i<=m;i++) { int l=1; int r=g[0]; for (int j=1;j<=g[0];j++) if (num[j]>1&&g[j]*2==ak[i]) mark[i]+=opt*num[j]*(num[j]-1); while (l<r) { if (g[l]+g[r]<ak[i]) l++; else { if (g[l]+g[r]==ak[i]) mark[i]+=opt*num[l]*num[r]; r--; } } } } void work(int x) { cal(x,0,1); vis[x]=1; for (int i=point[x];i;i=next[i]){ if (vis[v[i]]) continue; cal(v[i],len[i],-1); sum=son[v[i]]; root=0; getroot(v[i],x); work(root); } } int main() { freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1;i<n;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); } for (int i=1;i<=m;i++) scanf("%d",&ak[i]); sum=n; f[0]=1000000000; root=0; getroot(1,0); work(root); for (int i=1;i<=m;i++) if(mark[i]>0||!ak[i]) printf("Yes\n"); else printf("No\n"); }
0 0
- BZOJ 1316: 树上的询问 点分治
- bzoj 1316: 树上的询问 (点分治)
- BZOJ 1316: 树上的询问 点分治题解
- 【BZOJ 1316】 树上的询问 树分治
- [BZOJ1316]树上的询问(点分治+二分)
- 【bzoj1316】【树上的询问】【点分治+map】
- BZOJ 3784|树上的路径|点分治|堆|RMQ
- 【BZOJ 3697】采药人的路径 树上点分治
- [BZOJ 3784][树上的路径][点分治+堆]
- bzoj1316 树上的询问(多个定值树链询问)
- bzoj 3784: 树上的路径 (ST表+优先队列+点分治)
- 树上基于点的分治
- bzoj 1316(点分治)
- [可持久化可并堆 || ST表 点分治] BZOJ 3784 树上的路径
- BZOJ 2152 聪聪可可 (树上点分治)
- [bzoj 2152] 聪聪可可 树上点分治
- POJ 1741 Tree(树上的点分治)
- POJ 1741 树上 点的 分治
- OpenSSL 的使用详解
- A strange lift
- 到底要不要买securecrt的license
- 用类别添加方法可能存在的问题
- springMvc入门--初识springMvc
- bzoj 1316: 树上的询问 (点分治)
- 微信支付注意事项--Android版
- Spark快速大数据分析 第4章
- 洛谷1115 最大子段和
- IAR编译信息-size解读
- 京东消息中间件JMQ
- 关于Nessus的服务启动与插件更新
- spring中使用redis做缓存
- 约瑟夫问题