Fork me on GitHub

ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS

题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小。 意思应该都能明白。

解法:考虑将这棵树摆直如下:

那么我们可以把最中间的那条直径边删掉,然后在分成的两颗子树内求一个直径中心点,那么这两个点就可以作为答案。 反正当时就觉得这样是正确的, 但是不能证明。

于是,几个bfs就可以搞定了。

当时写TLE了,原因是存要删的边我用了map<pair<int,int>,int>, 后来改掉就不T了,map这种东西还是尽量少用。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
using namespace std;
#define N 200007

int vis[N],fa[N];
int maxi,maxtag;
struct node
{
    int dis,u;
};
vector<int> G[N];
int U,V;

void bfs(int S)
{
    node now;
    now.u = S;
    now.dis = 0;
    maxi = 0, maxtag = S;
    queue<node> que;
    fa[S] = -1;
    memset(vis,0,sizeof(vis));
    que.push(now);
    vis[S] = 1;
    while(!que.empty())
    {
        node tmp = que.front();
        que.pop();
        int dis = tmp.dis;
        int u = tmp.u;
        if(dis > maxi)    //最远的点
            maxi = dis, maxtag = u;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i];
            if(vis[v]) continue;
            if((u == U && v == V)||(u == V && v == U)) continue;
            now.dis = dis+1;
            now.u = v;
            fa[v] = u;
            vis[v] = 1;
            que.push(now);
        }
    }
}

int Smaxi,Smaxtag;
int Emaxi,Emaxtag;

void findcenter(int S,int& ma,int& tag)
{
    ma = 0, tag = S;
    bfs(S);
    int NS = maxtag;
    bfs(NS);
    int NE = maxtag;
    int cnt = (maxi+1)/2;
    int nc = 0;
    int i = NE;
    while(1)
    {
        nc++;
        if(nc > cnt)
        {
            tag = i;
            break;
        }
        i = fa[i];
    }
    bfs(tag);
    ma = maxi;
}

int main()
{
    int t,n,i,u,v;
    scanf("%d",&t);
    while(t--)
    {
        U = V = -1;
        scanf("%d",&n);
        for(i=0;i<=n;i++)
            G[i].clear();
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        bfs(1);
        int S = maxtag;
        bfs(S);
        int E = maxtag;
        int cnt = (maxi+1)/2;
        int nc = 0;
        i = E;
        while(1)
        {
            nc++;
            if(nc >= cnt)
            {
                U = i, V = fa[i];
                break;
            }
            i = fa[i];
        }
        findcenter(S,Smaxi,Smaxtag);
        findcenter(E,Emaxi,Emaxtag);
        printf("%d %d %d\n",max(Smaxi,Emaxi),Smaxtag,Emaxtag);
    }
    return 0;
}
View Code

 

posted @ 2014-10-14 17:56  whatbeg  阅读(531)  评论(0编辑  收藏  举报