zoukankan      html  css  js  c++  java
  • 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
    ",max(Smaxi,Emaxi),Smaxtag,Emaxtag);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    刷题238. Product of Array Except Self
    刷题236. Lowest Common Ancestor of a Binary Tree
    刷题208. Implement Trie (Prefix Tree)
    A1070
    A1048
    A1050
    A1041
    A1092
    A1084
    n进制转十进制
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4024936.html
Copyright © 2011-2022 走看看