poj1741 分类: poj 2015-02-08 03:40 101人阅读 评论(0) 收藏
poj1741
题意:找出图中距离不大于k的点对的数目
解法:
将无根树转化为有根树
首先可以想到枚举,时间复杂度
挖掘题目的信息,发现
满足条件的点对有两种情况:
1>两个点的路径经过树根
2>两个点位于同一颗子树中。
又因为:
所以路径经过
这样就可以在
于是采用点分治,分治复杂度
时间总复杂度
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
#define MAXN 10005
#define MAXN2 20005
int n,k;
struct edge{int v,w,next;}mp[MAXN2];
int head[MAXN],ml;
int ba[MAXN],s[MAXN];
int bowl[MAXN],l;
int flag[MAXN];
int ans,swap;
void newedge(int u0,int v0,int w0)
{
++ml;
mp[ml].v=v0;
mp[ml].w=w0;
mp[ml].next=head[u0];
head[u0]=ml;
}
inline void dfsroot(int a,int fa)
{
int i,p;
bowl[++l]=a;
s[a]=1,ba[a]=0;
for(i=head[a];i;i=mp[i].next)
if((p=mp[i].v)!=fa && !flag[p])
{
dfsroot(p,a);
s[a]+=s[p];
if(s[p]>ba[a])
ba[a]=s[p];
}
}
inline void dfsbowl(int a,int len,int fa)
{
int i,p;
bowl[++l]=len;
for(i=head[a];i;i=mp[i].next)
if((p=mp[i].v)!=fa && !flag[p])
{
dfsbowl(p,len+mp[i].w,a);
}
}
inline int getroot(int a)
{
int i,p,q,ret;
l=0;
dfsroot(a,0);
ret=bowl[1];
for(i=1;i<=l;i++)
{
p=bowl[i],q=s[a]-s[p];
if(q>ba[p])ba[p]=q;
if(ba[p]<ba[ret])ret=p;
}
return ret;
}
inline void sort(int a,int b)
{
int i=a,j=b;
int t=bowl[rand()%(b-a+1)+a];
while(i<=j)
{
while(bowl[i]<t)i++;
while(bowl[j]>t)j--;
if(i<=j)
{
swap=bowl[i];
bowl[i]=bowl[j];
bowl[j]=swap;
i++,j--;
}
}
if(a<j)sort(a,j);
if(i<b)sort(i,b);
}
inline int calculate(int x,int l0)
{
int i,j,ret=0;
l=0;dfsbowl(x,l0,0);
if(l>1)sort(1,l);
for(i=1,j=l;i<=l && j>i;i++)
{
while(bowl[i]+bowl[j]>k && j>i)j--;
ret+=j-i;
}
return ret;
}
inline void work(int a)
{
int i,p,root=getroot(a);
flag[root]=1;
ans+=calculate(root,0);
for(i=head[root];i;i=mp[i].next)
if(!flag[p=mp[i].v])
{
ans-=calculate(p,mp[i].w);
}
for(i=head[root];i;i=mp[i].next)
if(!flag[p=mp[i].v])
{
work(p);
}
}
int main()
{
int i,a,b,c;
#ifndef ONLINE_JUDGE
freopen("poj1741.in","r",stdin);
freopen("Poj1741.out","w",stdout);
#endif
while(1)
{
scanf("%d%d",&n,&k);
if(!n && !k)break;
ans=ml=0;
memset(head,0,sizeof(head));
memset(flag,0,sizeof(flag));
for(i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
newedge(a,b,c);newedge(b,a,c);
}
work(n);
printf("%d\n",ans);
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。