ZOJ 3820 Building Fire Stations(树的直径+操作)

来源:互联网 发布:玉溪超市软件yxqlkj 编辑:程序博客网 时间:2024/06/10 13:07

题意:

给出n个点,n-1条边的一棵树,然后要在两个点上建立两个消防站,让所有点的到消防站最大距离的点的这个距离最小。

分析:

首先先求这个树的直径,然后在树的直径的中点处把树分成两棵树,然后在把两棵树分别取中点的最大值就是ans值。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<queue>using namespace std;const int maxn = 2*1e5 + 100;int vis[maxn], fa[maxn];vector<int> G[maxn];vector<int> P;int bfs(int s, int t){    queue<int> Q;    P.clear();    memset(vis, 0, sizeof(vis));    memset(fa, -1, sizeof(fa));    int ans = 1, k = s;    vis[s] = 1;    Q.push(s);    vis[t] = -1;    while(!Q.empty())    {        int x = Q.front();        Q.pop();        for(int i = 0; i < G[x].size(); i++)        {            int v = G[x][i];            if(vis[v] != 0)                continue;            vis[v] = vis[x] + 1;            fa[v] = x;            if(ans < vis[v])            {                ans = vis[v];                k = v;            }            Q.push(v);        }    }    for(int i = k; i != -1; i = fa[i])        P.push_back(i);    return k;}pair<int, int> get_ans(int s, int t){    int p1 = bfs(s, t);    int p2 = bfs(p1, t);    int len = P.size()/2;    int x = P[len];    pair<int, int> ans(x, len);    return ans;}struct Node{    int one, two, len;    Node(int o, int t, int l) : one(o), two(t), len(l) {}};Node station(int s, int t){    int len = -1, one = -1, two = -1;    pair<int, int> st;    st = get_ans(s, t);    len = max(len, st.second);    one = st.first;    st = get_ans(t, s);    len = max(len, st.second);    two = st.first;    return Node(one, two, len);}void solve(int n){    Node ans(-1, -1, -1), res(-1, -1, -1);    int p1 = bfs(1, n+1);    int p2 = bfs(p1, n+1);    int len = P.size()/2;    int a = P[len-1], b = P[len], c = P[len+1];    if(P.size()%2 == 0)    {        ans = station(a, b);    }    else    {        ans = station(a, b);        res = station(b, c);        if(ans.len > res.len)            ans = res;    }    printf("%d %d %d\n", ans.len, ans.one, ans.two);}int main(){    int T, n, a, b;    scanf("%d", &T);    while(T--)    {        scanf("%d", &n);        for(int i = 0; i <= n; i++)            G[i].clear();        for(int i = 1; i < n; i++)        {            scanf("%d%d", &a, &b);            G[a].push_back(b);            G[b].push_back(a);        }        solve(n);    }    return 0;}


0 0
原创粉丝点击