cf293E Close Vertices(树分治+BIT)
2016-02-15 14:26
316 查看
E. Close Vertices
You've got a weighted tree, consisting of n vertices. Each edge has a non-negative weight. The length of the path between any two vertices of the tree is the number of edges in the path. The weight of the path is the total weight of all edges it contains.
Two vertices are close if there exists a path of length at most l between them and a path of weight at most w between them. Count the number of pairs of vertices v, u (v < u), such that vertices v and u are close.
Input
The first line contains three integers n, l and w (1 ≤ n ≤ 105, 1 ≤ l ≤ n, 0 ≤ w ≤ 109). The next n - 1 lines contain the descriptions of the tree edges. The i-th line contains two integers pi, wi (1 ≤ pi < (i + 1), 0 ≤ wi ≤ 104), that mean that the i-th edge connects vertex (i + 1) and pi and has weight wi.
Consider the tree vertices indexed from 1 to n in some way.
Output
Print a single integer — the number of close pairs.
Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.
Sample test(s)
Input
Output
Input
Output
【思路】
树分治。大体思路和这道题相似。
不同的是有两个需要满足的条件,只需要把dis排序,扫描的同时用BIT维护dep的区间信息并统计答案即可。
【代码】
View Code
You've got a weighted tree, consisting of n vertices. Each edge has a non-negative weight. The length of the path between any two vertices of the tree is the number of edges in the path. The weight of the path is the total weight of all edges it contains.
Two vertices are close if there exists a path of length at most l between them and a path of weight at most w between them. Count the number of pairs of vertices v, u (v < u), such that vertices v and u are close.
Input
The first line contains three integers n, l and w (1 ≤ n ≤ 105, 1 ≤ l ≤ n, 0 ≤ w ≤ 109). The next n - 1 lines contain the descriptions of the tree edges. The i-th line contains two integers pi, wi (1 ≤ pi < (i + 1), 0 ≤ wi ≤ 104), that mean that the i-th edge connects vertex (i + 1) and pi and has weight wi.
Consider the tree vertices indexed from 1 to n in some way.
Output
Print a single integer — the number of close pairs.
Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.
Sample test(s)
Input
4 4 6 1 3 1 4 1 3
Output
4
Input
6 2 17 1 3 2 5 2 13 1 6 5 9
Output
9
【思路】
树分治。大体思路和这道题相似。
不同的是有两个需要满足的条件,只需要把dis排序,扫描的同时用BIT维护dep的区间信息并统计答案即可。
【代码】
#include<map> #include<cstdio> #include<cstring> #include<vector> #include<iostream> #include<algorithm> #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; typedef long long LL; const int N = 1e5+10; const int INF = 1e9+10; struct Edge { int v,w; Edge(int v=0,int w=0) :v(v),w(w){} }; int n,W,L; LL ans; int root,size,vis ,siz ,f ,dis ,dep ,l1,l2; pair<int,int> list ; vector<int> rec; vector<Edge> g ; //BIT int C ; void add(int x,int v) { while(x<=n) C[x]+=v,x+=x&(-x); } int query(int x) { int ans=0; while(x>0) ans+=C[x],x-=x&(-x); return ans; } //fenzhi void getroot(int u,int fa) { siz[u]=1; f[u]=0; for(int i=0;i<g[u].size();i++) { int v=g[u][i].v; if(v!=fa && !vis[v]) { getroot(v,u); siz[u]+=siz[v]; f[u]=max(f[u],siz[v]); } } f[u]=max(f[u],size-siz[u]); if(f[u]<f[root]) root=u; } void getdis(int u,int fa) { list[++l1]=make_pair(dis[u],dep[u]); for(int i=0;i<g[u].size();i++) { int v=g[u][i].v; if(v!=fa && !vis[v]) { dep[v]=dep[u]+1; dis[v]=dis[u]+g[u][i].w; getdis(v,u); } } } LL getans(int l,int r) { sort(list+l,list+r+1); LL res=0; int j=l; for(int i=r;i>=l;i--) { while(j<=r && list[i].first+list[j].first<=W) { add(list[j].second,1); rec.push_back(list[j].second); j++; } if(list[i].first*2<=W && list[i].second*2<=L) res--; res+=(LL)query(L-list[i].second); } return res/2; } void clear() { for(int i=0;i<rec.size();i++) add(rec[i],-1); rec.clear(); } void solve(int u) { vis[u]=1; l1=l2=0; LL S1=0,S2=0; for(int i=(int)g[u].size()-1;i>=0;i--) { int v=g[u][i].v; if(!vis[v]) { l2=l1+1; dep[v]=1; dis[v]=g[u][i].w; getdis(v,u); clear(); S1+=getans(l2,l1); } } FOR(i,1,l1) //AT:根为终点 if(list[i].first<=W && list[i].second<=L) S2++; clear(); //AT:clear S2+=getans(1,l1); ans=ans+S2-S1; for(int i=(int)g[u].size()-1;i>=0;i--) { int v=g[u][i].v; if(!vis[v]) { size=siz[v]; root=0; getroot(v,-1); solve(root); } } } void read(int& x) { char c=getchar(); int f=1; x=0; while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();} while(isdigit(c)) x=x*10+c-'0',c=getchar(); x*=f; } int main() { //freopen("in.in","r",stdin); //freopen("out.out","w",stdout); read(n),read(L),read(W); int u,v,w; FOR(i,2,n) { read(u),read(v),read(w); g[u].push_back(Edge(v,w)); g[v].push_back(Edge(u,w)); } root=0,f[0]=INF,size=n; getroot(1,-1); solve(root); cout<<ans; return 0; }
View Code
相关文章推荐
- 一次失败的Selenium chromedriver切换
- 抽取数据shell
- KindEditor显示了源码
- Enterprise Integration Pattern - 组成简介
- iOS 7中自动布局教程
- oracle表分区详解
- 微信加粉方法(很使用很全面)
- linux下删去文件中包含某个字符串的行
- 鹅厂揭秘——高端大气的App电量測试
- 关于电脑开机网络图标一直转圈的问题
- nyist67 三角形面积(叉乘求三角形的面积)
- git 的应用学习
- C++ 运算符重载与友元函数的简单运用实例
- web开发中文字符乱码解决集合文
- Spring MVC 系列(五)——Spring MVC上传功能源码
- 求人的技巧 要许以好处。
- 修改 Ueditor 默认显示的字体大小
- 【Regular Expression】常用的正则表达式
- 有关大数的运算(1)
- Hive数据存储各种模式