【JZOJ4715】【NOIP2016提高A组模拟8.19】树上路径
2016-09-03 11:15
447 查看
题目描述
给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E。(k为路径p上的边的权值和)输入
第一行给出N,S,E。N代表树的点数,S,E如题目描述。下面N-1行给出这棵树的相邻两个节点的边及其权值W。
输出
输出共一行一个整数,表示答案。若无解输出-1。样例输入
5 10 402 4 80
2 3 57
1 2 16
2 5 49
样例输出
16样例解释
1到2的路径即为答案。数据范围
对于20%的数据满足n<=300对于50%的数据满足n<=3000
对于60%的数据满足n<=10^5
对于以上数据,满足|E-S|<=50
对于100%的数据满足n<=10^5,|E-S|<=10^6
对于所有数据满足1<=Wi<=1000,|E|,|S|<=10^9
解法
树上路径问题使用树分治解决。对于当前树,维护一个Dis数组表示,当前树中的每个点到当前树根结点的距离。
依次遍历当前根结点的子树,得出来一个dis表示这个子树的结点到当前根结点的距离。考虑合并Dis和dis,对于每个dis[i],在Dis中二分出一个Dis[j]使得Dis[j]+dis[i]>=S,然后更新答案。
最后把dis并入Dis维护有序性即可。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #define sqr(x) ((x)*(x)) #define ln(x,y) int(log(x)/log(y)) using namespace std; const char* fin="aP2.in"; const char* fout="aP2.out"; const int inf=0x7fffffff; const int maxn=100007,maxm=2*maxn,maxde=31; int n,m1,m2,i,j,k,l,tot,siz,root,ans=inf; int fi[maxn],la[maxm],va[maxm],ne[maxm]; int dis[maxn],Dis[maxn]; bool bz[maxn]; void add_line(int a,int b,int c){ tot++; ne[tot]=fi[a]; la[tot]=b; va[tot]=c; fi[a]=tot; } void getsize(int v,int from){ int i,j,k; if (!from) siz=0; siz++; for (k=fi[v];k;k=ne[k]) if (!bz[la[k]] && la[k]!=from) getsize(la[k],v); } int getroot(int v,int from){ int i=1,j=1,k,tmp; for (k=fi[v];k;k=ne[k]){ if (!bz[la[k]] && la[k]!=from) { tmp=getroot(la[k],v); if (tmp>siz/2) i=0; j+=tmp; } } if (i && j>siz/2) root=v; return j; } void getdis(int v,int from,int st){ int i,j,k; if (st>m2) return; dis[++dis[0]]=st; for (k=fi[v];k;k=ne[k]){ if (la[k]!=from && !bz[la[k]]){ getdis(la[k],v,st+va[k]); } } } void merge(){ int i,j,k,l,r,mid; for (i=1;i<=dis[0];i++){ l=1; r=Dis[0]; while (l<r){ mid=(l+r)/2; if (dis[i]+Dis[mid]>=m1) r=mid; else l=mid+1; } if (dis[i]+Dis[l]>=m1) ans=min(ans,dis[i]+Dis[l]); } for (i=1;i<=dis[0];i++) Dis[++Dis[0]]=dis[i]; sort(Dis+1,Dis+Dis[0]+1); } void dfs(int v,int de){ int i,j,k; Dis[0]=1; Dis[1]=0; bz[v]=true; for (k=fi[v];k;k=ne[k]){ if (!bz[la[k]]){ dis[0]=0; getdis(la[k],v,va[k]); merge(); } } for (k=fi[v];k;k=ne[k]) if (!bz[la[k]]){ getsize(la[k],0); getroot(la[k],0); dfs(la[k],de+1); } } int main(){ scanf("%d%d%d",&n,&m1,&m2); for (i=1;i<n;i++){ scanf("%d%d%d",&j,&k,&l); add_line(j,k,l); add_line(k,j,l); } getsize(1,0); getroot(1,0); dfs(1,0); if (ans>m2) printf("-1"); else printf("%d",ans); return 0; }
启发
树上路径问题使用树上分治。树上分治处理方法并不单一,须灵活运用。
相关文章推荐
- JZOJ 4715 【NOIP2016提高A组模拟8.19】树上路径
- 【NOIP2016提高A组模拟8.19】树上路径
- 【NOIP2016提高A组模拟8.19】(雅礼联考day2)树上路径
- JZOJ.4715【NOIP2016提高A组模拟8.19】树上路径
- [JZOJ 4714]【NOIP2016提高A组模拟8.19】公约数
- JZOJ.4714【NOIP2016提高A组模拟8.19】公约数
- JZOJ 4714 【NOIP2016提高A组模拟8.19】公约数
- jzoj5290 【NOIP2017提高组A组模拟8.17】行程的交集 (树上路径交,dfs序+树状数组维护姿势)
- JZOJ 4786 【NOIP2016提高A组模拟9.17】小a的强迫症
- JZOJ 4787 【NOIP2016提高A组模拟9.17】数格子
- [JZOJ 4699][CF583C]【NOIP2016提高A组模拟8.15】Password
- [JZSC2016 Part 2] 【NOIP2016提高A组模拟8.19】总结
- [jzoj4711]【NOIP2016提高A组模拟8.17】Binary
- {题解}[jzoj4778]【NOIP2016提高A组模拟9.14】数列编辑器
- JZOJ 4819 【NOIP2016提高A组模拟10.15】算循环
- JZOJ [4820]. 【NOIP2016提高A组模拟10.15】最大化
- JZOJ4744. 【NOIP2016提高A组模拟9.2】同余 一类比较好的分类思想+根号算法
- 【NOIP2016提高A组模拟9.4】树上摩托
- JZOJ4708. 【NOIP2016提高A组模拟8.20】奇洛金卡达 倒着做的思想+并查集维护
- 【JZOJ4782】【NOIP2016提高A组模拟9.15】Math