链接
http://www.lydsy.com/JudgeOnline/problem.php?id=3365
题解
和bzoj1468是一样的吧,连样例、数据规模都完全一样。
代码
//点分治
#include <cstdio>
#include <algorithm>
#define maxn 50000
#define forp for(int p=head[pos];p;p=nex[p])if(to[p]^pre and !grey[to[p]])
using namespace std;
int M, S, head[maxn], nex[maxn<<1], to[maxn<<1], w[maxn<<1], dist[maxn], size[maxn],
list[maxn], G, sumG, ans, K, grey[maxn], tot, N;
inline void adde(int a, int b, int v)
{to[++tot]=b;w[tot]=v;nex[tot]=head[a];head[a]=tot;}
inline int calc()
{
int l=1, r=*list, cnt=0;
sort(list+1,list+*list+1);
while(l<r)
{
while(l<r and list[l]+list[r]>K)r--;
while(l<r and list[l]+list[r]<=K)cnt+=r-l,l++;
}
return cnt;
}
void dfs(int pos , int pre)
{
list[++*list]=dist[pos];
forp dfs(to[p],pos);
}
void calc_dist(int pos, int pre)
{
list[++*list]=dist[pos];
forp dist[to[p]]=dist[pos]+w[p], calc_dist(to[p],pos);
}
int calc_size(int pos, int pre)
{
size[pos]=1;
forp size[pos]+=calc_size(to[p],pos);
return size[pos];
}
void findG(int pos, int pre, int sum)
{
// printf("pos=%d sum=%d\n",pos,sum);
if(sum<sumG)G=pos, sumG=sum;
forp findG(to[p],pos,sum+(*size-size[to[p]])*w[p]-size[to[p]]*w[p]);
}
void solve(int pos)
{
int p, x=0;
if(G)*list=0, dfs(pos,-1), ans-=calc();
dist[pos]=0, *list=0, calc_dist(pos,-1);
calc_size(pos,-1), *size=size[pos];
G=pos; for(int i=1;i<=*list;i++)x+=list[i]; sumG=x;
findG(pos,-1,x);
grey[G]=1;
dist[G]=0, *list=0, calc_dist(G,-1);
ans+=calc();
for(p=head[G];p;p=nex[p])if(!grey[to[p]])solve(to[p]);
}
void init()
{
int i, a, b, v;
char s[5];
scanf("%d%d",&N,&M);
for(i=1;i<=M;i++)scanf("%d%d%d%s",&a,&b,&v,s), adde(a,b,v), adde(b,a,v), S=a;
scanf("%d",&K);
}
int main()
{
init();
solve(S);
printf("%d",ans);
return 0;
}