zoj3820(树的直径的应用)

来源:互联网 发布:ipv4网络访问权限win10 编辑:程序博客网 时间:2024/05/19 04:56
题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。

思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。

代码如下:

#include <stdio.h>#include <string.h>#include <algorithm>#include <map>#include <queue>#include <vector>#include <string>#include <iostream>#define inf 0x3f3f3f3f#define N 200005using namespace std;int head[N],tot;struct node{    int v,next;}edge[N<<1];void addedge(int u,int v){    edge[tot].next = head[u];    edge[tot].v = v;    head[u] = tot++;}int step[N],vis[N],pre[N];int x,y;int bfs(int u,int& cnt){    memset(vis,0,sizeof(vis));    queue<int> q;    q.push(u);    step[u] = 0;    vis[u] = 1 ;    pre[u] = -1;    int now;    while(!q.empty())    {        now = q.front();        q.pop();        for(int i = head[now]; i != -1; i = edge[i].next)        {            int v = edge[i].v;            if(vis[v])  continue;            if(now == x && v == y)  continue;            if(now == y && v == x)  continue;            step[v] = step[now] + 1;            //if(step[v] > ans)   ans = step[v];            cnt = max(cnt,step[v]);            vis[v] = 1;            pre[v] = now;            q.push(v);        }    }    return now;}int find_node(int u,int dist){    int cnt = 1;    while(1)    {        if(cnt == dist/2)   break;        u = pre[u];        cnt++;    }    return u;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        memset(head,-1,sizeof(head));        tot = 0;  x = y = inf;        int n;        scanf("%d",&n);        int i;        for(i = 1; i < n; i++)        {            int u,v;            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);        }        int st = bfs(1,i);        int ed = bfs(st,i);        //cout<<st<<" "<<ed<<endl;        //for(i = 1; i <= n; i++)          //  cout<<step[i]<<" ";cout<<endl;       //cout<<step[ed]<<endl;        x = find_node(ed,step[ed]+2);        y = pre[x];//找到要去除的边x - y        //cout<<x<<" "<<y<<endl;        int st1 = bfs(st,i);        int ed1 = bfs(st1,i);        int ans1 = find_node(ed1,step[ed1]+2);        int st2 = bfs(ed,i);        int ed2 = bfs(st2,i);        int ans2 = find_node(ed2,step[ed2]+2);        int ans = 0,temp = 0;        bfs(ans1,temp);     ans = max(ans,temp);        temp = 0;        bfs(ans2,temp);     ans = max(ans,temp);        printf("%d %d %d\n",ans, ans1,ans2);    }    return 0;}


0 0