这题貌似用启发式合并的话复杂度为nlogn,然而我不会,于是用 树状数组写的,复杂度 n(logn)2,跑了900多ms。 用树状数组有一个坑,就是树状数组的下表从1 开始,但是可能存在路径上关键节点为0的情况,那么我们给每条路径关键节点个数加一,就避免了这种情况。还有一个问题是如果根节点本身是关键节点的话,需要把两条路径的个数的和减1.
还有就是树状数组清空如果memset会超时,于是我记录了修改的节点进行复原。感觉好丑陋。。。
去学启发式合并的方法去了QAQ
#include <bits/stdc++.h>
using namespace std;
typedef int lint;
typedef long long LL;
const lint maxn = 200000 + 5;
const lint maxm = 400000 + 5;
const lint inf = 0x3f3f3f3f;
lint key[maxn],he[maxn],ne[maxm],ver[maxm],tot,b[maxn],k,cost[maxm],vis[maxn],cnt[maxn],g[maxn],sz[maxn],d[maxn],ans,root,sum;
void add_edge( lint x,lint y,lint c ){
ver[++tot] = y;
ne[tot] = he[x];
he[x] = tot;
cost[tot] = c;
}
void init_b( lint k ){
for( lint i = 0;i <= k;i++ ) b[i] = -inf;
}
lint lowbit( lint x ){
return x&(-x);
}
void add( lint x,lint v ){
while( x <= k ){
b[x] = max(b[x], v);
x += lowbit(x);
}
}
lint ask( lint x ){
lint re = -inf;
while( x ){
re = max(re, b[x]);
x -= lowbit(x);
}
return re;
}
void init(){
memset( he,0,sizeof(he) );
memset( key,0,sizeof(key) );
memset( vis,0,sizeof(vis) );
tot = 1;
ans = 0;
}
vector<lint> ve;
void dfs_cnt( lint x,lint f,lint dis,lint c ){
cnt[x] = c;
d[x] = dis;
ve.push_back(x);
if( key[x] ) { cnt[x]++; c++;}
if( !key[root] && k - c >= 1 )
ans = max( ans,dis+ask( k-c ) );
else if( key[root] && k+1-c >= 1 ){
ans = max( ans,dis+ask( k+1-c ) );
}
for( lint cure = he[x];cure;cure = ne[cure] ){
lint y = ver[cure];
if( vis[y] || y == f ) continue;
dfs_cnt( y,x,dis+cost[cure],c );
}
}
void get_root(lint x,lint f)
{
sz[x]=1;g[x]=0;
for(int cure = he[x];cure;cure= ne[cure]){
lint y = ver[cure];
if( vis[y] || y == f ) continue;
get_root(y,x);
g[x]=max(g[x],sz[y]);
sz[x]+=sz[y];
}
g[x]=max(g[x],sum-sz[x]);
if(g[x]<g[root])root=x;
}
void init_b2( lint x ){
while( x <= k ){
b[x] = -inf;
x += lowbit(x);
}
}
vector<lint> ve2;
void dfs_div( lint x ){
vis[x] = 1;
if( key[x] ) add( 2,0 );
else add(1,0);
ve2.clear();
for( lint cure = he[x];cure;cure = ne[cure] ){
lint y = ver[cure];
if( vis[y] ) continue;
ve.clear();
if( key[x] )
dfs_cnt( y,x,cost[cure],2 );
else dfs_cnt( y,x,cost[cure],1 );
for( lint i = 0;i < ve.size();i++ ){
lint t = ve[i];
ve2.push_back(t);
add( cnt[t],d[t] );
}
}
if( key[x] ) init_b2(2);
else init_b2(1);
for( lint i = 0;i < ve2.size();i++ ){
init_b2( cnt[ve2[i]] );
}
for( lint cure = he[x];cure;cure = ne[cure] ){
lint y = ver[cure];
if( vis[y] ) continue;
root = 0;sum = sz[y];
get_root( y,x );
dfs_div( root );
}
}
int main() {
lint n,m;
scanf("%d%d%d",&n,&k,&m);
k += 2;
init();init_b(k);
for( lint x, i = 1;i <= m;i++ ){
scanf("%d",&x);
key[x] = 1;
}
for( lint x,y,c, i = 1;i <= n-1;i++ ){
scanf("%d%d%d",&x,&y,&c);
add_edge( x,y,c );
add_edge( y,x,c );
}
sum = n;g[0] = n;root = 0;
get_root( 1,0 );
dfs_div(root);
printf("%d",ans);
return 0;
}