BZOJ1509 NOI2003 逃学的小孩

Description:

Input:

第一行是两个整数N(3  N  200000)和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1Ui, Vi  N,1  Ti  1000000000),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟。街道信息不会重复给出。

Output:

仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris。

 

思路:由于规则2,可知题目给出的是一棵树

然后求一根直径,两个家就在直径两端

两端各遍历一发,就可以知道每个点到两端的距离,然后取出每个点到两端的最小距离再加上直径长度即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N = 1e6 + 10;
 
int head[N], now;
struct edges{
    int to, next, w;
}edge[N<<1];
void add(int u, int v, int w){ edge[++now] = {v, head[u], w}; head[u] = now;}
 
long long n, m, d[N], l, r, f[N];
int bfs(int x){
    queue<int> q;
    memset(d, 0x3f, sizeof(d));
    q.push(x); d[x] = 0;
    while(!q.empty()){
        int x = q.front(); q.pop();
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to;
            if(d[v] > d[x] + edge[i].w){
                d[v] = d[x] + edge[i].w;
                q.push(v);
            }
        }
    }
    for(int i = 1; i <= n; i++)
      if(d[i] > d[x]) x = i;
    return x;
}
int main(){
    scanf("%lld%lld",&n, &m);
    int x, y, z;
    for(int i = 1; i <= m; i++){
        scanf("%d%d%d",&x, &y, &z);
        add(x, y, z);  add(y, x, z);
    }
    l = bfs(1);
    r = bfs(l);
    memcpy(f, d, sizeof(d));
    bfs(r);
    long long mx = 0;
    for(int i = 1; i <= n; i++)
      mx = max(mx, min(d[i], f[i])+ f[r]);
    printf("%lld\n", mx);
    return 0;
}
View Code

 

posted @ 2018-04-05 23:31  Ror_shach  阅读(254)  评论(0编辑  收藏  举报