Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 15927 | Accepted: 5194 |
Description
Input
Output
Sample Input
5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0
Sample Output
8
Source
树的点分治裸题
树的点分治的思想就是对于一棵树,先找出树的重心,然后统计不同子树间的答案(同时也要减去同一棵子树中多统计的答案),再递归每一棵子树。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 10005 using namespace std; int n,k,cnt,tot,mn,root,ans; int head[maxn],sz[maxn],mx[maxn],dis[maxn]; bool vst[maxn]; struct edge_type{int next,to,w;}e[maxn*2]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add_edge(int x,int y,int z) { e[++cnt]=(edge_type){head[x],y,z};head[x]=cnt; e[++cnt]=(edge_type){head[y],x,z};head[y]=cnt; } inline void dfssize(int x,int fa) { sz[x]=1; mx[x]=0; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (y!=fa&&!vst[y]) { dfssize(y,x); sz[x]+=sz[y]; mx[x]=max(mx[x],sz[y]); } } } inline void dfsroot(int rt,int x,int fa) { mx[x]=max(mx[x],sz[rt]-sz[x]); if (mx[x]<mn) mn=mx[x],root=x; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (y!=fa&&!vst[y]) dfsroot(rt,y,x); } } inline void dfsdis(int x,int d,int fa) { dis[++tot]=d; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (y!=fa&&!vst[y]) dfsdis(y,d+e[i].w,x); } } inline int calc(int x,int d) { int ret=0; tot=0; dfsdis(x,d,0); sort(dis+1,dis+tot+1); int i=1,j=tot; while (i<j) { while (dis[i]+dis[j]>k&&i<j) j--; ret+=j-i; i++; } return ret; } inline void dfs(int x) { mn=n; dfssize(x,0); dfsroot(x,x,0); ans+=calc(root,0); vst[root]=true; for(int i=head[root];i;i=e[i].next) { int y=e[i].to; if (!vst[y]) { ans-=calc(y,e[i].w); dfs(y); } } } int main() { n=read();k=read(); while (n) { memset(head,0,sizeof(head)); memset(vst,false,sizeof(vst)); cnt=ans=0; F(i,1,n-1) { int x=read(),y=read(),z=read(); add_edge(x,y,z); } dfs(1); printf("%d\n",ans); n=read();k=read(); } return 0; }