题目大意:
给定一棵N个节点、边上带权的树,再给出一个K,询问有多少个点对(u,v)满足dis[u,v]<=K。
数据规模:
给定一棵N个节点、边上带权的树,再给出一个K,询问有多少个点对(u,v)满足dis[u,v]<=K。
数据规模:
多组测试数据,N≤10000,1≤边权≤1000,1≤K≤10^9。
马克:楼天城男人必做8题之一.... 目前只做了这一题
http://wenku.baidu.com/view/60c6aa1ffc4ffe473368aba8.html
上面网址是讲解思路的论文,具体实现没说。。
首先是要找到重心,那么先递归求出每个点拆掉后能够得到的最大的点的个数,这个点的个数最小的肯定是重心。
然后就按照论文讲解的方法求点对数量,先要求出每个点到重心的距离。
下面是代码:#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
using namespace std;
const int MAXN = 10100;
const int inf = 0x7f7f7f7f;
typedef pair<int,int> PII;
int n,k;
int vis[MAXN],fa[MAXN];
int mson[MAXN],son[MAXN];
int nod[MAXN],ns;
int dis[MAXN],ds;
int ans;
vector<PII >vv[MAXN];
void dfs(int u,int p)
{
son[u]=1;
mson[u]=0;
nod[ns++]=u;
int siz=vv[u].size();
for(int i=0;i<siz;i++)
{
int v=vv[u][i].first;
if(vis[v]||v==p) continue;
dfs(v,u);
son[u]+=son[v];
mson[u]=max(mson[u],son[v]);
}
}
int getroot(int u)//求重心
{
ns=0;
dfs(u,-1);
int mi=MAXN,res=-1;
for(int i=0;i<ns;i++)
{
mson[nod[i]]=max(mson[nod[i]],son[u]-son[nod[i]]);//每个点拆掉后能够得到的最大的点的个数
if(mson[nod[i]]<mi)
{
mi=mson[nod[i]];
res=nod[i];
}
}
return res;
}
void getdis(int u,int d,int p)//求出子节点到根的距离
{
dis[ds++]=d;
int siz=vv[u].size();
for(int i=0;i<siz;i++)
{
int v=vv[u][i].first;
if(vis[v]||v==p) continue;
getdis(v,d+vv[u][i].second,u);
}
}
void calc(int u,int t)
{
sort(dis,dis+ds);
int i=dis[0]?0:1,j=ds-1;
while(i<j)
{
if(dis[i]+dis[j]<=k)
{
ans+=(j-i)*t;
i++;
}
else j--;
}
}
void solve(int u)
{
u=getroot(u);
ds=0;
getdis(u,0,-1);
calc(u,1); //求以u为根的子节点可以构成多少对
vis[u]=1;
for(int i=0;i<ds;i++)
if(dis[i]<=k&&dis[i]!=0) ans++;//以根为起点的个数
int siz=vv[u].size();
for(int i=0;i<siz;i++)
{
int v=vv[u][i].first;
if(vis[v]) continue;
ds=0;
getdis(v,vv[u][i].second,-1);
calc(v,-1); //减去属于同一个子树的重复点对
solve(v);
}
}
int main()
{
while(~scanf("%d%d",&n,&k)&&(n||k))
{
for(int i=0;i<=n;i++) vv[i].clear();
for(int i=1;i<n;i++)
{
int u,v,l;
scanf("%d%d%d",&u,&v,&l);
vv[u].push_back(make_pair(v,l));
vv[v].push_back(make_pair(u,l));
}
ans=0;
memset(vis,0,sizeof(vis));
solve(1);
printf("%d\n",ans);
}
}