zoj3820 Building Fire Stations 树的中心

题意:n个点的树,给出n-1条边,每条边长都是1,两个点建立防火站,使得其他点到防火站的最远距离最短。

思路:比赛的时候和队友一开始想是把这两个点拎起来,使得层数最少,有点像是树的中心,于是就猜测是将树的中心找到后,将两棵左右子树分别求树的中心,这两棵树的中心就是答案,but另外一个队友又说了个反例,脑子也不清醒,以为还有没考虑到的,比赛也没A,赛后一想就是最初的猜想,回来之后写了写,报栈了,数据范围太大,真不想改,今天改了改,改成bfs又tle了,囧囧的,把memset和memcpy都改成循环AC了,代码写的很不优雅。

如果最一开始树的直径是偶数,即1-2-3-4,则拆成1-2和3-4。

如果最一开始树的直径是奇数,即1-2-3-4-5,则拆成1-2-3和3-4-5。

丑丑的代码:

  1 /*===============================================================
  2 *   Copyright (C) 2014 All rights reserved.
  3 *
  4 *   File Name: zoj3172.cpp
  5 *   Author:sunshine
  6 *   Created Time: 2014年10月14日
  7 *
  8 ================================================================*/
  9 #include <map>
 10 #include <queue>
 11 #include <math.h>
 12 #include <stdio.h>
 13 #include <string.h>
 14 #include <iostream>
 15 #include <algorithm>
 16 
 17 using namespace std;
 18 
 19 #define N 500010
 20 
 21 int head[N];
 22 int edgeNum;
 23 struct Edge{
 24     int v,to;
 25 }edge[N];
 26 int edge_u_v[N][2];
 27 
 28 void addedge(int a,int b){
 29     edge[edgeNum].v = b;
 30     edge[edgeNum].to = head[a];
 31     head[a] = edgeNum ++;
 32 }
 33 
 34 int vis[N],depth,ind;
 35 int t_vis[N],father[N];
 36 int stack[N];
 37 void bfs(int u){
 38     vis[u] = 1;
 39     queue<int>que;
 40     que.push(u);
 41     while(!que.empty()){
 42         int tmp = que.front();
 43         que.pop();
 44         if(vis[tmp] >= depth){
 45             depth = vis[tmp];
 46             ind = tmp;
 47         }
 48         for(int i = head[tmp];i != -1;i = edge[i].to){
 49             int v = edge[i].v;
 50             if(vis[v] == 0){
 51                 vis[v] = vis[tmp] + 1;
 52                 father[v] = tmp;
 53                 que.push(v);
 54             }
 55         }
 56     }
 57     int tmp = ind;
 58     for(int i = 0;i < depth;i ++){
 59         stack[i] = tmp;
 60         tmp = father[tmp];
 61     }
 62     return ;
 63 }
 64 
 65 
 66 void init(int n){
 67     edgeNum = 0;
 68     //memset(head,-1,sizeof(head));
 69     //memset(vis,0,sizeof(vis));
 70     //memset(father,-1,sizeof(father));
 71     for(int i = 0;i <= n;i ++) {
 72         head[i] = -1;
 73         vis[i] = 0;
 74         father[i] = -1;
 75     }
 76 }
 77 
 78 int main(){
 79     int t;
 80     int n;
 81     int u,v;
 82     //freopen("data.in","r",stdin);
 83     //freopen("data.out","w",stdout);
 84     scanf("%d",&t);
 85     while(t --){
 86         scanf("%d",&n);
 87 
 88         init(n);
 89         for(int i = 0;i < n - 1;i ++){
 90             scanf("%d%d",&u,&v);
 91             edge_u_v[i][0] = u;
 92             edge_u_v[i][1] = v;
 93             addedge(u,v);
 94             addedge(v,u);
 95         }
 96 
 97         depth = 1;
 98         bfs(1);
 99         for(int i = 0;i <= n;i ++) vis[i] = 0;
100         bfs(ind);
101 
102         int ans_one,ans_two;
103         int depth_one,depth_two;
104         //left graph
105         init(n);
106         u = stack[depth / 2 - 1];//chai bian
107         v = stack[depth / 2];
108         for(int i = 0;i < n - 1;i ++){
109             if((edge_u_v[i][0] == u && edge_u_v[i][1] == v)
110             || (edge_u_v[i][1] == u && edge_u_v[i][0] == v)) ;
111             else{
112                 addedge(edge_u_v[i][0],edge_u_v[i][1]);
113                 addedge(edge_u_v[i][1],edge_u_v[i][0]);
114             }
115         }
116 
117         int seperation = stack[depth / 2];//the seperation of left and right
118         int seperation1 = stack[(depth - 1) / 2];
119         int long_depth = depth;
120         depth = 1;
121         bfs(seperation);
122         for(int i = 0;i <= n;i ++) t_vis[i] = vis[i];
123         for(int i = 0;i <= n;i ++) vis[i] = 0;
124         bfs(ind);
125         ans_one = stack[depth/2];//if depth&1 mid else right
126         depth_one = depth;
127 
128         if(long_depth&1){
129             addedge(u,v);
130             addedge(v,u);
131             t_vis[seperation] = 0;
132         }else{
133             seperation = seperation1;
134         }
135         depth = 1;
136         for(int i = 0;i <= n;i ++) vis[i] = t_vis[i];
137         bfs(seperation);
138         for(int i = 0;i <= n;i ++) vis[i] = t_vis[i];
139         bfs(ind);
140         if(depth & 1) ans_two = stack[depth/2];
141         else ans_two = stack[(depth-1)/2];
142         depth_two = depth;
143 
144         if(ans_one == ans_two){
145             printf("%d %d %d
",long_depth/2,ans_one,(ans_one == 1)?2:1);
146         }else{
147             printf("%d %d %d
",max(depth_one/2,depth_two/2),ans_one,ans_two);
148         }
149 
150     }
151     return 0;
152 }
View Code
原文地址:https://www.cnblogs.com/-sunshine/p/4029172.html