标签:
poj1741树上的点对
题目大意:给定一棵树,求树上距离不超过k的点对个数。
思路:点分治模板题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #define maxnode 10005 #define inf 2100000000LL using namespace std; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},va[maxnode*2]={0}, siz[maxnode]={0},tot=0,maxn,root,ans=0,k,n; bool visit[maxnode]={0}; vector<int> dis; void add(int u,int v,int w) { ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v;va[tot]=w; ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u;va[tot]=w; } void getroot(int u,int fa,int nn) { int i,maxsiz=0,j; siz[u]=1; for (i=point[u];i;i=next[i]) { if (!visit[j=en[i]]&&j!=fa) { getroot(j,u,nn);siz[u]+=siz[j]; maxsiz=max(maxsiz,siz[j]); } } maxsiz=max(maxsiz,nn-siz[u]); if (maxsiz<maxn) { maxn=maxsiz;root=u; } } void getdep(int u,int dep,int fa) { int i; dis.push_back(dep);siz[u]=1; for (i=point[u];i;i=next[i]) if (en[i]!=fa&&!visit[en[i]]) { getdep(en[i],dep+va[i],u);siz[u]+=siz[en[i]]; } } int cal(int u,int dep) { int sum=0,i,j; dis.clear();getdep(u,dep,0); sort(dis.begin(),dis.end()); for (i=0,j=dis.size()-1;i<j;) { if (dis[i]+dis[j]<=k) { sum+=j-i;++i; } else --j; } return sum; } void work(int u) { int i,j; ans+=cal(u,0);visit[u]=true; for (i=point[u];i;i=next[i]) { if (!visit[en[i]]) { ans-=cal(en[i],va[i]); maxn=siz[en[i]]; getroot(en[i],root=0,siz[en[i]]); work(root); } } } int main() { freopen("poj1741_tree.in","r",stdin); freopen("poj1741_tree.out","w",stdout); int i,j,u,v,w; while(scanf("%d%d",&n,&k)==2) { if (n==0&&k==0) break; tot=0;memset(visit,false,sizeof(visit)); memset(point,0,sizeof(point)); for (i=1;i<n;++i) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); } maxn=n;ans=0; getroot(1,root=0,n); work(root); printf("%d\n",ans); } }
hdu4670Cube number on a tree
题目大意:给定一棵树,每个点都有一个权值,可以分为一些给定质数的和(质数个数不超过30),求出一些路径的条数,使路径都满足路上点权乘积是个立方数。
思路:我们对于每一个点都分解质因数,保存下每种的个数,满足条件的路径就是那些点的相应因数个数相加后%3=0的路径了。
点分,对每一个点统计路径个数,减去重复的就可以了。
对于统计答案的部分,我们dfs求出到点到重心路径上的和,把这个30位的数组转成一个三进制数,放到map里。穷举每一个map里面的数,找到互补的数,贡献给答案就可以了。这里注意如果这个数和互补数一样的话,ans的计算方式略有不同。
对于重复的部分,我们减去的时候要时刻注意变量的含义。
这道题目的思维和代码量都中等,但是结合起来莫名的很难写(蒟蒻的吐槽),要认真思考好每一个部分的实现。
标签:
原文地址:http://www.cnblogs.com/Rivendell/p/4603194.html