【SSL 1463】旅行

题目大意:

一颗 (n) 个节点的树,一段路径的长度是每个点一奇一偶取相反数,求这棵树内经过道路数为奇数的 (k) 短路。

正文:

搜索出每一个节点到根节点的长度 (dis_i),然后树的奇偶层分成两个部分,然后两个部分进行匹配。

题目大意:

struct edge
{
	ll from, to, next, w;
}e[N];
ll head[N], tot, total;

struct node
{
	ll val, dep;
}dis[N];

struct recc
{
	ll x, y, len;
};

bool operator <(const recc &a, const recc &b)
{
	return a.len > b.len;
}
priority_queue <recc> que;

void add(ll u, ll v, ll w)
{
	e[++tot] = (edge){u, v, head[u], w}, head[u] = tot;
}

int cmp (node a, node b)
{
	if((a.dep & 1) == (b.dep & 1)) return a.val < b.val;
	return (a.dep & 1) < (b.dep & 1);
}

void dfs(ll fa, ll x, ll step, ll isneg)     // Get dis
{
	dis[x].dep = step;
	for (int i = head[x]; i; i = e[i].next)
	{
		int y = e[i].to;
		if(fa == y) continue;
		dis[y].val = isneg * e[i].w + dis[x].val;
		dfs (x, y, step + 1, -isneg);
	}
	if(step & 1) dis[x].val = -dis[x].val;
}

int main()
{
	scanf ("%lld%lld", &n, &m);
	for (int i = 1; i < n; i++)
	{
		ll u, v, w;
		scanf ("%lld%lld%lld", &u, &v, &w);
		add(u, v, w);
		add(v, u, w);
	} 
	dfs(0, 1, 1, 1);
	sort (dis + 1, dis + 1 + n, cmp);
	ll dis2pos = 0;
	for (int i = 1; i <= n; i++) if(dis[i].dep % 2 == 1){dis2pos = i;break;}
	que.push((recc){1, dis2pos, dis[1].val + dis[dis2pos].val});
	for (int i = 1; i < m; i++)
	{
		if(que.empty()) break;
		recc a = que.top();
		que.pop();
		if(a.x < (dis2pos - 1) && a.y == dis2pos) 
			que.push((recc){a.x + 1, dis2pos, dis[a.x + 1].val + dis[dis2pos].val}); 
		if(a.y < n) 
			que.push((recc){a.x, a.y + 1, dis[a.x].val + dis[a.y + 1].val}); 
	}
	if(que.empty())
		puts("Stupid Mike");
	else
		printf("%lld", que.top().len);
	return 0;
}


原文地址:https://www.cnblogs.com/GJY-JURUO/p/13480587.html