Building Fire Stations 39届亚洲赛牡丹江站B题

题意:
     给你一棵树,让你再里面选取两个点作为**点,然后所有点的权值是到这两个点中最近的那个的距离,最后问距离中最长的最短是多少,输出距离还有那两个点(spj特判)。


思路:
     现场赛的时候我们压根就没看这道题,还有k题也是水题,可惜当时我们读的题意不对<以为数字可以随意断开,然后拼接的数组可以再段。。>,最后只过了3个题,拿了个铜,不过没啥遗憾,因为这是第一次去亚洲赛,没空手而归就是好事,下几场放开了打就行了。

回到这个题目,其实这个题目我们可以判定的是这两个点分别"罩着"两棵树<原因是最后的答案已经是小于等于树的直径的一半的,如果在同一侧,那么答案就大于等于直径的一半了>,这两颗树一定是整个树从直径断开的分成的两颗树,那么我们就两遍广搜分成两颗树,然后再在两颗树上分别找直径,然后两个点就是直径的中点,然后答案就是两个塔到所有自己所在的那颗子树上所有点的最大距离的最大距离,其他的还有一些细节,比如分成两颗树后有一棵树只剩1个点的时候,去中点可能弄错,这个地方注意点,具体细节可以看代码


#include<stdio.h>
#include<string.h>
#include<queue>

#define N_node 200000 + 10
#define N_edge 400000 + 20

using namespace std;

typedef struct
{
   int node ,t;
}NODE;

typedef struct
{
   int to ,next;
}STAR;

NODE xin ,tou;
STAR E[N_edge];
int list[N_node] ,tot;
int mer[N_node] ,mark[N_node];
int root[N_node];

void add(int a ,int b)
{
   E[++tot].to = b;
   E[tot].next = list[a];
   list[a] = tot;
   E[++tot].to = a;
   E[tot].next = list[b];
   list[b] = tot;
}

int maxx ,mknode;
void BFS(int s ,int aa ,int bb)
{
   queue<NODE>q;
   memset(mark ,0 ,sizeof(mark));
   xin.node = s ,xin.t = 0;
   mark[s] = 1;
   q.push(xin);
   maxx = 0 ,mknode = s;
   while(!q.empty())
   {
      tou = q.front();
      q.pop();
      if(maxx < tou.t)
      {
         maxx = tou.t;
         mknode = tou.node;
      }
      for(int k = list[tou.node] ;k ;k = E[k].next)
      if(!mark[E[k].to])
      {
         xin.node = E[k].to;
         xin.t = tou.t + 1;
         if(aa == tou.node && bb == xin.node || aa == xin.node && bb == tou.node)
         continue;
         mer[xin.node] = tou.node;
         mark[E[k].to] = 1;
         q.push(xin);
      }
   }
}

int main ()
{
   int n ,t ,i ,a ,b;
   scanf("%d" ,&t);
   while(t--)
   {
      scanf("%d" ,&n);
      memset(list ,0 ,sizeof(list)) ,tot = 1;
      for(i = 1 ;i < n ;i ++)
      {
         scanf("%d %d" ,&a ,&b);
         add(a ,b);
      }
      
      BFS(1 ,-1 ,-1);
      int mk1 = mknode; 
      BFS(mk1 ,-1 ,-1);
      int mk2 = mknode;
      int nowid = 0;
      int x = mk2;
      while(x != mk1)
      {
         root[++nowid] = x;
         x = mer[x];
      }
      
      root[++nowid] = mk1;
      
      int aa = root[nowid/2];
      int bb = root[nowid/2+1];
      
      BFS(aa ,aa ,bb);
      mk1 = mknode;
      BFS(mk1 ,aa ,bb);
      mk2 = mknode;
      nowid = 0;
      x = mk2;
      while(x != mk1)
      {
         root[++nowid] = x;
         x = mer[x];
      }
      root[++nowid] = mk1;
      
      //for(i = 1 ;i <= nowid ;i ++)
      //printf("%d *
" ,root[i]);
      //puts("");
      
      int aaa = root[nowid/2+1]; 
      
      BFS(bb ,aa ,bb);
      mk1 = mknode;
      BFS(mk1 ,aa ,bb);
      mk2 = mknode;
      nowid = 0;
      x = mk2;
      while(x != mk1)
      {
         root[++nowid] = x;
         x = mer[x];
      }
      root[++nowid] = mk1;
      int bbb = root[nowid/2+1];
      
      BFS(aaa ,aa ,bb);
      int Ans1 = maxx;
      BFS(bbb ,aa ,bb);
      int Ans2 = maxx;
      int Ans = Ans1 > Ans2 ? Ans1 : Ans2;
      printf("%d %d %d
" ,Ans ,aaa ,bbb);
   }
   return 0;
}

原文地址:https://www.cnblogs.com/csnd/p/12062705.html