2282: [Sdoi2011]消防

来源:互联网 发布:8年的php程序员工资 编辑:程序博客网 时间:2024/06/09 20:20

2282: [Sdoi2011]消防

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 499  Solved: 323
[Submit][Status][Discuss]

Description

某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000)。
这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的行业是消防业。由于政府对国民的热情忍无可忍(大量的消防经费开销)可是却又无可奈何(总统竞选的国民支持率),所以只能想尽方法提高消防能力。
现在这个国家的经费足以在一条边长度和不超过s的路径(两端都是城市)上建立消防枢纽,为了尽量提高枢纽的利用率,要求其他所有城市到这条路径的距离的最大值最小。
你受命监管这个项目,你当然需要知道应该把枢纽建立在什么位置上。

Input

输入包含n行:
第1行,两个正整数n和s,中间用一个空格隔开。其中n为城市的个数,s为路径长度的上界。设结点编号以此为1,2,……,n。
从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。

Output

输出包含一个非负整数,即所有城市到选择的路径的最大值,当然这个最大值必须是所有方案中最小的。

Sample Input

【样例输入1】
5 2
1 2 5
2 3 2
2 4 4
2 5 3



【样例输入2】
8 6
1 3 2
2 3 2
3 4 6
4 5 3
4 6 4
4 7 2
7 8 3

Sample Output

【样例输出1】

5
【样例输出2】

5

HINT

对于100%的数据,n<=300000,边长小等于1000。

Source

stage 2 day1

[Submit][Status][Discuss]

题解

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<cmath>#include<vector>#include<queue>using namespace std;const int maxn = 3E5 + 30;struct E{int to,w;};int n,ans = ~0U>>1,m,s,t,l[maxn],fa[maxn],r[maxn],fw[maxn];int f[maxn],p[maxn],vis[maxn],dis[maxn],road[maxn];vector <E> v[maxn];queue <int> q;int bfs(int k,int ti){dis[k] = 0; vis[k] = ti;int len = 0; q.push(k);while (!q.empty()) {int x = q.front(); q.pop();for (int i = 0; i < v[x].size(); i++) {int to = v[x][i].to;if (vis[to] == ti) continue;fa[to] = x; fw[to] = v[x][i].w;dis[to] = dis[x] + fw[to]; len = max(len,dis[to]);vis[to] = ti; q.push(to);}}return len;}int main(){#ifdef YZY   freopen("yzy.txt","r",stdin);#endifcin >> n >> m;for (int i = 1; i < n; i++) {int x,y,z; scanf("%d%d%d",&x,&y,&z);v[x].push_back((E){y,z});v[y].push_back((E){x,z});}int ti = 0;bfs(1,++ti);for (int i = 1; i <= n; i++)if (dis[i] > dis[s]) s = i;bfs(s,++ti);for (int i = 1; i <= n; i++)if (dis[i] > dis[t]) t = i;n = 0; ++ti;for (;;) {road[++n] = t;vis[t] = ti;t = fa[t];if (road[n] == s) break;}for (int i = 1; i <= n; i++) l[i] = dis[road[1]] - dis[road[i]];for (int i = n; i; i--) r[i] = dis[road[i]];for (int i = 1; i <= n; i++) f[i] = bfs(road[i],ti);int L,R,head,tail;tail = R = 0; head = 1;for (L = 1; L <= n; L++) {while (p[head] < L && head <= tail) ++head;while (R < n && l[R+1] - l[L] <= m) {while (head <= tail && f[p[tail]] <= f[R+1]) --tail;p[++tail] = ++R;}ans = min(ans,max(f[p[head]],max(l[L],r[R])));}cout << ans;return 0;}


0 0
原创粉丝点击