http://codeforces.com/problemset/problem/337/D
给一棵树 其中有m个点是重要点 一个点到这m给点的距离都小于等于d才算符合条件 问有多少点符合条件
把这m个点想象成m个半径为d的圆 题目就是问有多少点被这m个半径相同的圆全部覆盖 可以想到要求m个点中相距最远的两个点 具体怎么求其实就是树的直径的变形了
一个点要符合条件 肯定要满足最严苛的这两个点 判一下就好
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node
{
int v;
int next;
};
node edge[2*maxn];
int first[maxn],p[maxn],dis1[maxn],dis2[maxn];
int n,m,d,num,p1,p2;
void addedge(int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
}
void dfs(int *dis,int cur,int fa)
{
int i,v;
for(i=first[cur];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(v!=fa)
{
dis[v]=dis[cur]+1;
dfs(dis,v,cur);
}
}
}
int main()
{
int i,u,v,maxx,ans;
scanf("%d%d%d",&n,&m,&d);
for(i=1;i<=m;i++) scanf("%d",&p[i]);
memset(first,-1,sizeof(first));
num=0;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dis1[p[1]]=0;
dfs(dis1,p[1],0);
maxx=-1;
for(i=1;i<=m;i++) if(maxx<dis1[p[i]]) maxx=dis1[p[i]],p1=p[i];
dis1[p1]=0;
dfs(dis1,p1,0);
maxx=-1;
for(i=1;i<=m;i++) if(maxx<dis1[p[i]]) maxx=dis1[p[i]],p2=p[i];
dis2[p2]=0;
dfs(dis2,p2,0);
/*
printf("*%d %d*\n",p1,p2);
for(i=1;i<=n;i++) printf("%d ",dis1[i]);
printf("\n");
for(i=1;i<=n;i++) printf("%d ",dis2[i]);
printf("\n");
*/
ans=0;
for(i=1;i<=n;i++)
{
if(dis1[i]<=d&&dis2[i]<=d) ans++;
}
printf("%d\n",ans);
return 0;
}