首页 > 代码库 > zoj3820 Building Fire Stations 树的中心

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 graph105         init(n);106         u = stack[depth / 2 - 1];//chai bian107         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 right118         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 right126         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\n",long_depth/2,ans_one,(ans_one == 1)?2:1);146         }else{147             printf("%d %d %d\n",max(depth_one/2,depth_two/2),ans_one,ans_two);148         }149 150     }151     return 0;152 }
View Code

 

zoj3820 Building Fire Stations 树的中心