题解:
最近学数分学到意识模糊,做到OI题冷静一下。
联通块强制选根,然后用dfs序转化为一个路径然后就是做K短路了。
用点分治即可在图大小为 O ( n log n ) O(n \log n) O(nlogn)的图上做K短路,时间复杂度 O ( n log 2 n + k log k ) O(n \log ^2 n + k\log k) O(nlog2n+klogk)。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int,int> pii;
typedef pair <LL,int> pLi;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e5+50;
int n,k,a[N],G;
vector <int> edge[N];
int vis[N],dep[N],fa[N],sze[N],mx,total;
inline void calcG(int x,int f) {
int mx_son=0;
sze[x]=1;
for(auto v:edge[x])
if(!vis[v] && (v^f)) {
calcG(v,x);
sze[x]+=sze[v];
mx_son=max(mx_son,sze[v]);
}
mx_son=max(mx_son,total-sze[x]);
if(mx>mx_son) G=x, mx=mx_son;
}
inline void dfs(int x,int f) {
sze[x]=1;
for(auto v:edge[x])
if(!vis[v] && (v^f)) dfs(v,x), sze[x]+=sze[v];
}
inline void solve(int x,int f) {
dep[x]=dep[f]+1;
fa[x]=f; vis[x]=1;
for(auto v:edge[x])
if(!vis[v]) {
dfs(v,x);
total=mx=sze[v];
calcG(v,x);
solve(G,x);
}
}
namespace KSP {
const int src=1, des=2, N=3345678, M=23456789;
int g[N],nt[N],vt[N],ec,tot=2;
LL w[N],dis[N]; int vis[N],isfa[N];
inline void add(int x,int y,LL ww) {nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; w[ec]=ww;}
struct node {
node *lc,*rc;
int dis; pLi val;
} *rt[N],Pool[M],*pool=Pool;
inline node* newnode(pLi v=pLi(0,0)) {
node *t=++pool;
t->lc=t->rc=NULL;
t->dis=0; t->val=v;
return t;
}
struct data {
node* now;
LL base;
data(node *now,LL base) : now(now),base(base) {}
friend inline bool operator <(const data &a,const data &b) {
return a.base+a.now->val.first>b.base+b.now->val.first;
}
};
inline node* merge(node *x,node *y) {
if(!x) return y;
if(!y) return x;
if(x->val>y->val) swap(x,y);
node *z=newnode(); *z=*x;
z->rc=merge(z->rc,y);
if(!z->lc || (z->rc && z->rc->dis>z->lc->dis)) swap(z->lc,z->rc);
z->dis=(z->rc ? z->rc->dis : -1)+1;
return z;
}
inline void getdis() {
for(int i=2;i<=tot;i++) dis[i]=1e18;
for(int e=g[1];e;e=nt[e])
dis[vt[e]]=min(dis[vt[e]],(LL)w[e]);
for(int i=3;i<=tot;i++)
for(int e=g[i];e;e=nt[e])
dis[vt[e]]=min(dis[vt[e]],dis[i]+w[e]);
for(int i=1;i<=tot;i++)
for(int e=g[i];e;e=nt[e])
if(!isfa[vt[e]] && dis[vt[e]]==dis[i]+w[e]) isfa[vt[e]]=i;
else rt[vt[e]]=merge(rt[vt[e]],newnode(pLi(w[e]-(dis[vt[e]]-dis[i]),i)));
}
int exi[N];
inline void dfs2(int x) {
if(!isfa[x] || exi[x]) return;
exi[x]=1;
dfs2(isfa[x]);
rt[x]=merge(rt[x],rt[isfa[x]]);
}
inline void solve() {
getdis();
if(k==1) {cout<<dis[2]<<'\n'; return;}
k--;
for(int i=1;i<=tot;i++) dfs2(i);
priority_queue <data> q;
q.push(data(rt[2],0));
while(k) {
k--;
node *u=q.top().now;
LL base=q.top().base;
q.pop();
if(!k) {cout<<dis[2]+base+u->val.first<<'\n'; return;}
if(u->lc) q.push(data(u->lc,base));
if(u->rc) q.push(data(u->rc,base));
if(rt[u->val.second])
q.push(data(rt[u->val.second],base+u->val.first));
}
}
}
using KSP::add;
using KSP::tot;
int dfn[N],ord[N],ind;
inline void pre(int x,int lim,int f=0) {
dfn[x]=++ind;
ord[ind]=x;
sze[x]=1;
for(auto v:edge[x])
if((v^f) && dep[v]>lim)
pre(v,lim,x), sze[x]+=sze[v];
}
inline void build(int x) {
ind=0; pre(x,dep[x]);
add(1,tot+1,0);
for(int i=1;i<=ind;i++) {
int u=ord[i], sz=sze[u];
add(tot+dfn[u],(dfn[u]==ind) ? KSP::des : (tot+dfn[u]+1),a[u]);
if(u!=x) add(tot+dfn[u],(dfn[u]+sz>ind) ? KSP::des : (tot+dfn[u]+sz),0);
} tot+=ind;
}
int main() {
n=rd(), k=rd();
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
edge[x].push_back(y);
edge[y].push_back(x);
}
for(int i=1;i<=n;i++) a[i]=rd();
mx=total=n;
calcG(1,0);
solve(G,0);
for(int i=1;i<=n;i++) build(i);
KSP::solve();
}