POJ 1987 Distance Statistics
2016-07-14 19:16
393 查看
http://poj.org/problem?id=1987
题意:给一棵树,求树上有多少对节点满足距离<=K
思路:点分治,我们考虑把每个距离都存起来,然后排序,一遍扫描计算一下,注意还要减掉自己加自己的方案。而且,我们还要去掉走到同一个子树的方案。复杂度:O(nlog^2n)
题意:给一棵树,求树上有多少对节点满足距离<=K
思路:点分治,我们考虑把每个距离都存起来,然后排序,一遍扫描计算一下,注意还要减掉自己加自己的方案。而且,我们还要去掉走到同一个子树的方案。复杂度:O(nlog^2n)
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> #define ll long long int tot,go[1000005],first[1000005],next[1000005]; ll st[1000005],val[1000005]; int sum,son[1000005],root,n,F[1000005],c[1000005]; int pd[1000005],sz,vis[1000005]; ll dis[1000005]; int cnt,K,ans; int read(){ int t=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} return t*f; } void insert(int x,int y,int z){ tot++; go[tot]=y; next[tot]=first[x]; first[x]=tot; val[tot]=z; } void add(int x,int y,int z){ insert(x,y,z);insert(y,x,z); } void findroot(int x,int fa){ son[x]=1;F[x]=0; for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (pur==fa||vis[pur]) continue; findroot(pur,x); son[x]+=son[pur]; F[x]=std::max(F[x],son[pur]); } F[x]=std::max(F[x],sum-son[x]); if (F[x]<F[root]) root=x; } void bfs(int x){ int h=1,t=1;c[1]=x;pd[x]=sz;dis[x]=0; while (h<=t){ int now=c[h++]; for (int i=first[now];i;i=next[i]){ int pur=go[i]; if (vis[pur]||pd[pur]==sz) continue; pd[pur]=sz; dis[pur]=dis[now]+val[i]; c[++t]=pur; st[++cnt]=dis[pur]; } } std::sort(st+1,st+1+cnt); int j=cnt,res=0,Cnt=0; for (int i=1;i<=t;i++){ while (j>1&&st[i]+st[j]>K) j--; if (st[i]+st[j]<=K) res+=j; if (st[i]+st[i]<=K) Cnt++; } res-=Cnt; ans+=res/2; } int del(int x,int Dis){ dis[x]=Dis;sz++; int h=1,t=1;cnt=1;st[cnt]=Dis; pd[x]=sz;c[1]=x; while (h<=t){ int now=c[h++]; for (int i=first[now];i;i=next[i]){ int pur=go[i]; if (pd[pur]==sz||vis[pur]) continue; dis[pur]=dis[now]+val[i]; st[++cnt]=dis[pur]; pd[pur]=sz; c[++t]=pur; } } int j=cnt,res=0,Cnt=0; std::sort(st+1,st+1+cnt); for (int i=1;i<=t;i++){ while (j>1&&st[i]+st[j]>K) j--; if (st[i]+st[j]<=K) res+=j; if (st[i]+st[i]<=K) Cnt++; } res-=Cnt; return res/2; } void solve(int x){ vis[x]=1;++sz; cnt=1;st[cnt]=0; bfs(x); for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (vis[pur]) continue; ans-=del(pur,val[i]); } int Cnt=sum; for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (vis[pur]) continue; if (son[pur]>son[x]) sum=Cnt-son[x]; else sum=son[pur]; root=0; findroot(pur,x); solve(root); } } int main(){ int m; char s[20]; scanf("%d%d\n",&n,&m); for (int i=1;i<n;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); scanf("%s",s+1); } scanf("%d\n",&K); F[0]=0x7fffffff; root=0;sum=n; findroot(1,0); solve(root); printf("%d\n",ans); }
相关文章推荐
- Linux 下的 shell 编程之 for 循环
- Android相机,YV12ToRGB24,rgbToBitmap
- NDK的Linux的环境搭建(Eclipse篇)
- 【jzoj4624】【字符串匹配】【kmp】
- Linux 下的 shell 编程之 case 多分支选择
- 单片机小学期总结
- shell脚本杂七杂八问题
- TP3.2.3 in标签用法
- Linux 下的 shell 编程之 if-else选择结构
- Not enough space svn: zlib (uncompress): buffer error: Decompression of svndiff data failed
- STL---list(列表)
- for循环打印字典
- MyEclipse 2014+maven搭建web项目
- SIFT特征提取分析
- NDK开发详解
- 0714
- WebApp开发经验
- js模块编程
- hdu 5147(树状数组)
- 开通CSDN微博 记录