树型dp那里本来我是想保存每个节点向下不通过任意一个子节点的最大路径,但是这样时间复杂度最坏的情况下能达到O(n2),马上想到了可以记录每一个点到下一个点的次小路径,这样的话可以把时间复杂度严格的控制在O(n)。不过最后查询的时候只能那样搞了,区域赛的题搞个那种蛋疼的查询卡人真心没意思啊。。。
树形dp还是很有爱的,一次DFS()加一次BFS(),搜出 最小途径+次小途径+最小逆向途径~~再加上RMQ的O(1)最大最小查询~~就AC鸟~~~
时间还不错~~656ms能排第六~~
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<utility>
#include<complex>
#include<cstdlib>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cctype>
#include<limits>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<cmath>
#include<ctime>
#include<list>
#include<map>
#include<set>
using namespace std;
const int inf=0x7fffffff;
const int maxn=51111;
const int maxc=17;
struct zz
{
int way;
int id;
}tz;
int n,m;
int x,y,l,w,ans,lx,rx,tx;
vector<zz>g[maxn];
queue<int>q;
bool vis[maxn];
int fa[maxn];
int len[maxn];
int down[maxn][3]; //最小途径+次小途径+最小逆向途径
int dp[maxn];
int lg2[maxn];
int xx2[maxc];
int a[maxn][maxc]; //最大查询
int b[maxn][maxc]; //最小查询
void dfs(int v=1)
{
for(int i=0;i<g[v].size();i++)
{
if(vis[g[v][i].id])
{
continue;
}
fa[g[v][i].id]=v;
len[g[v][i].id]=g[v][i].way;
vis[g[v][i].id]=true;
dfs(g[v][i].id);
if(down[g[v][i].id][0] + g[v][i].way > down[v][0] )
{
down[v][1] = down[v][0];
down[v][0] = down[g[v][i].id][0] + g[v][i].way;
}
else if(down[g[v][i].id][0] + g[v][i].way > down[v][1])
{
down[v][1] = down[g[v][i].id][0] + g[v][i].way;
}
}
return ;
}
void bfs(int now=1,int temp=0)
{
memset(vis,0,sizeof(vis));
while(!q.empty())
{
q.pop();
}
vis[now]=true;
down[now][2]=0;
for(int i=0;i<g[now].size();i++)
{
if(vis[g[now][i].id])
{
continue;
}
vis[g[now][i].id]=true;
q.push(g[now][i].id);
}
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=0;i<g[now].size();i++)
{
if(vis[g[now][i].id])
{
continue;
}
vis[g[now][i].id]=true;
q.push(g[now][i].id);
}
temp=down[fa[now]][0];
if( temp == down[now][0] + len[now] )
{
temp = down[fa[now]][1];
}
down[now][2]=max(down[fa[now]][2],temp)+len[now];
}
return ;
}
void dpstart()
{
memset(vis,0,sizeof(vis));
memset(down,0,sizeof(down));
memset(dp,0,sizeof(dp));
fa[1]=0;
len[1]=0;
vis[1]=true;
dfs();
bfs();
for(int i=1;i<=n;i++)
{
dp[i]=max(down[i][0],down[i][2]);
}
return ;
}
void init()
{
int l=1,r=1;
lg2[1]=0;
for(int i=0;i<maxc;i++)
{
xx2[i]=1<<i;
}
for(int i=1;i<=maxc;i++)
{
l=xx2[i];
r=xx2[i+1];
for(int j=l; j<r && j<maxn ; j++ )
{
lg2[j]=i;
}
}
return ;
}
void rmq()
{
for( int i=1; i<=n; i++)
{
a[i][0] = dp[i];
b[i][0] = dp[i];
}
for ( int j=1; xx2[j] <= n; j++ )
{
for ( int i=1; i + xx2[j] -1 <=n; i++ )
{
a[i][j]=max(a[i][j-1],a[i+xx2[j-1]][j-1]);
b[i][j]=min(b[i][j-1],b[i+xx2[j-1]][j-1]);
}
}
return ;
}
inline int qa()
{
return max(a[lx][tx],a[rx-xx2[tx]+1][tx])-min(b[lx][tx],b[rx-xx2[tx]+1][tx]);
}
inline void query()
{
ans=1;
for(lx=1;lx<=n-ans;++lx)
{
for(rx=lx+ans;rx<=n;++rx)
{
tx=lg2[rx-lx+1];
if(qa() <= w)
{
ans++;
}
else
{
break;
}
}
}
return ;
}
int main()
{
init();
while(scanf("%d%d",&n,&m))
{
if(n==0 &&m==0)
{
break;
}
for(int i=1;i<=n;i++)
{
g[i].clear();
}
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&x,&y,&l);
tz.id=y;
tz.way=l;
g[x].push_back(tz);
tz.id=x;
g[y].push_back(tz);
}
dpstart();
rmq();
for(int i=1;i<=m;i++)
{
scanf("%d",&w);
query();
printf("%d\n",ans);
}
}
return 0;
}