bzoj2282 [SDOI2011]消防

题目

  bzoj2282

 

题解

  首先吐槽一发题意

  选择的路径可以不包含边???

  只包含一个节点也算路径???

  惹不起 惹不起

  然后我们就可以发现,离任意一点最远的点必然是直径的端点,所以所选路径至少有一点在树的直径上

  此时答案即为较远端点到当前点的距离

  剩下的点若不在直径上,无法更新直径端点到所选路径的距离,答案不变

  所以整条路径都在直径上答案是最优的

  于是二分

  (树的直径两遍bfs求得)

 

代码

  

#include <bits/stdc++.h>
using namespace std;
const int N = 300005;
const int M = 2 * N;

inline int read()
{
	int x = 0, f = 1; char ch = getchar();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
	return x * f;
}

int n, len;

struct node
{
	int fr, to, w, nt;
	node(int ff = 0, int tt = 0, int ww = 0, int nn = 0) {fr = ff; to = tt; w = ww; nt = nn;}
}E[M];
int num, p[N];

void add(int x, int y, int z) {E[++num] = node(x, y, z, p[x]); p[x] = num;}

int dis[N], from[N]; queue<int> q; bool mark[N];
void bfs(int s)
{
	memset(dis, -1, sizeof(dis));
	q.push(s); dis[s] = 0;
	while(!q.empty())
	{
		int x = q.front(); q.pop();
		for(int e = p[x]; e; e = E[e].nt)
		{
			int k = E[e].to;
			if(dis[k] != -1) continue;
			from[k] = x; q.push(k);
			if(mark[E[e].to]) dis[k] = dis[x];
			else dis[k] = dis[x] + E[e].w;
		}
	}
}

int dia, st[N];//st[i]记录i到s的距离
void get_dia()
{
	int s = 0, t = 0;
	bfs(1);
	for(int i = 1; i <= n; i++) if(dis[i] > dis[s]) s = i;
	bfs(s);
	for(int i = 1; i <= n; i++) if(dis[i] > dis[t]) t = i;
	dia = dis[t];
	st[++st[0]] = dis[t]; mark[t] = true;
	while(t != s)
	{
		st[++st[0]] = dis[from[t]];
		t = from[t]; mark[t] = true;
	}
	bfs(s);
}

bool check(int mid)
{
	int l = 1, r = st[0];
	while(st[1] - st[l + 1] <= mid && l <= st[0]) l++;
	while(st[r - 1] <= mid && r >= 1) r--;
	return st[l] - st[r] <= len;
}

int main()
{
	n = read(); len = read();
	for(int i =  1; i < n; i++)
	{
		int x = read(), y = read(), z = read();
		add(x, y, z); add(y, x, z);
	}
	get_dia();
	int l = 0, r = dia, ans = 0;
	for(int i = 1; i <= n; i++) ans = max(ans, dis[i]);
	if(len < dia)
		while(l <= r)
		{
			int mid = (l + r) >> 1;
			if(check(mid)) {ans = mid; r = mid - 1;}
			else l = mid + 1;
		}
	printf("%d", ans);
	return 0;
}

 

posted @ 2018-06-11 20:12  XYZinc  阅读(223)  评论(0编辑  收藏  举报