1. 程式人生 > >ZOJ 3820 Building Fire Stations

ZOJ 3820 Building Fire Stations

empty sca auto pac esp ++ vector sta amp

題意:
一棵樹中,選取兩點,使得(其他點到這兩點的距離的最小值)的最大值最小

思路:
考慮只選取一點的情況,那麽顯然選取直徑的中點即為答案。
首先考慮選取的兩點肯定在直徑上,因為假如不在直徑上,那麽把點往直徑上移動,不會使得答案變得更劣。
再考慮選取兩點,假如我們將樹按照樹的直徑的中點分成兩段,那麽肯定是一邊放一點。
因為假如兩個點都在一邊的話,答案肯定是\(\frac{len}{2}\)\(len\)為樹的直徑長度。
那麽既然兩個點分別在兩邊的話,那顯然是兩邊分別求個樹的直徑,再取中點放是最優的吧。

#include <bits/stdc++.h>
using namespace std;

#define N 200010
int n;
vector <int> G[N];

int fa[N], dep[N], far;
int get_far(int st)
{
    queue <int> q;      
    q.push(st);
    dep[st] = 1;
    fa[st] = -1;
    while (!q.empty())
    {
        int u = q.front(); q.pop();
        far = u;
        for (auto v : G[u]) if (v != fa[u])
        {
            fa[v] = u;
            dep[v] = dep[u] + 1;
            q.push(v);
        }
    }
}

void get_center(int st)
{
    get_far(st);
    get_far(far);
    int shift = dep[far] / 2;
    if (dep[far] % 2 == 0) --shift; 
    while (shift--)
        far = fa[far];
}


int main()
{
    int T; cin >> T;
    while (T--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
            G[i].clear();
        for (int i = 1, u, v; i < n; ++i)
        {
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        get_center(1);
        int center = far;
        for (vector <int> ::iterator it = G[center].begin(); it != G[center].end(); ++it)
            if (*it == fa[center])
            {
                G[center].erase(it);
                break;
            }   
        for (vector <int> :: iterator it = G[fa[center]].begin(); it != G[fa[center]].end(); ++it)
            if (*it == center)
            {
                G[fa[center]].erase(it);
                break;
            }
        int p1, p2, dis;
        get_center(fa[center]);
        p1 = far;
        dis = dep[p1];
        get_center(center);
        p2 = far;
        dis = max(dis, dep[p2]) - 1;
        printf("%d %d %d\n", dis, p1, p2);
    }
    return 0;
}

ZOJ 3820 Building Fire Stations