Description
Solution
经过观察,可以发现题目有一个比较不错的性质:
1、一条合法的路径必须由两条路径组成,一条是奇数,另一条是偶数。
所以我们可以先把每一个点到达根节点的路径求出来,深度为奇数的点放进一个
a
a
a数组里,偶数的放进
b
b
b数组里,再给他们分别进行排序。
然后进行两两结合,先把a数组里的所有数跟
b
1
b_{1}
b1结合,把路径丢进一个小根队里。每次取出堆顶,假设取出来的是
a
i
a_{i}
ai和
b
j
b_{j}
bj,那么我们就把
a
i
a_{i}
ai和
b
j
+
1
b_{j+1}
bj+1丢进堆里,第
k
k
k次取出来的堆顶就是答案。
可是还是有很多童鞋有疑惑:两个路径结合,他们可能会有重合的边呀?
答:但是两条路径的深度的奇偶性质并不相同,所以呢两个路径重合的部分,第一条路径是正数,第二条路径就是负数,反之,第一条路径是负数,第二条路径是正数,所以两两会抵消掉,这样我们就不用考虑了。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,m,cnt,tot,tot1=1,num;
int head[N],dep[N];
ll dis[N],heap[N][3],a[N],b[N];
struct node {
int to,next;
ll len;
}edge[N<<1];
void add(int x,int y,ll z) {
edge[cnt].to=y;
edge[cnt].len=z;
edge[cnt].next=head[x];
head[x]=cnt++;
}
void dfs(int now,int fa) {
for(register int i=head[now];i!=-1;i=edge[i].next) {
int son=edge[i].to;
ll len=edge[i].len;
if(son==fa)continue;
dep[son]=dep[now]+1;
dis[son]=-dis[now]+len;
if(dep[son]&1)a[++tot]=dis[son];
else b[++tot1]=dis[son];
dfs(son,now);
}
}
void Swap(int x,int y) {
swap(heap[x][0],heap[y][0]);
swap(heap[x][1],heap[y][1]);
swap(heap[x][2],heap[y][2]);
}
void up(int x) {
while(x>1&&heap[x][0]<heap[x>>1][0])
Swap(x,x>>1),x>>=1;
}
void down(int x) {
while(((x<<1)<=num&&heap[x][0]>heap[x<<1][0])||(((x<<1)|1)<=num&&heap[x][0]>heap[(x<<1)|1][0])) {
int y=x<<1;
if((y|1)<=num&&heap[y][0]>heap[y|1][0])y|=1;
Swap(x,y);
x=y;
}
}
int main() {
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
for(register int i=1;i<n;i++) {
int u,v;ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
b[1]=0;dep[0]=-1;
dfs(1,0);
sort(a+1,a+1+tot);
sort(b+1,b+1+tot1);
for(register int i=1;i<=tot;i++) {
heap[i][0]=a[i]+b[1];
heap[i][1]=i;heap[i][2]=1;
}
num=tot;
for(register int i=1;i<m;i++) {
if(!num) {
puts("Stupid Mike");
return 0;
}
int x=heap[1][1],y=heap[1][2];
Swap(1,num);
--num;down(1);
if(y+1<=tot1) {
heap[++num][0]=a[x]+b[y+1];
heap[num][1]=x;heap[num][2]=y+1;
up(num);
}
}
printf("%lld",heap[1][0]);
fclose(stdin);
fclose(stdout);
return 0;
}