树上选两点(使最短)树的直径+bfs
题意:
给你一颗树,让你放两个点,放在哪里的时候任意点到某个最近的消防站最远值最小。
思路:
树的直径类题目。
首先我们想两个点会把整棵树分成两个团,所以肯定会在树的某个链上切开。
而且要切一定切在树的直径上,如果不切在直径上,那有一个团的最场距离不就是(直径长度lenth/2了吗)。
所以我们取出直径,枚举切在哪里。
左右两半边的计算方法是一样的,如下图:
我们先算出直径上每个节点的最长距离,因为对于某一个节点,它的分支的长度它到不会超过到直径两端的长度,这样我们就很好算了。
跑两遍:第一次从左到右对左半边的团的直径前缀记录下来,第二次从右到左对右半边的直径后缀记录下来
(注意:1. 对lenth取max,2. 如果直径是偶数如:8,lenth要记为5,mid+1)
最后再跑一遍记录答案就行了。
1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\草稿.txt","r",stdin); 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr 13 #include <string> 14 #include <time.h>//srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 15 #include <cmath> 16 #include <deque> 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less 18 #include <vector>//emplace_back 19 //#include <math.h> 20 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor 21 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare) 22 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation 23 #define fo(a,b,c) for(register int a=b;a<=c;++a) 24 #define fr(a,b,c) for(register int a=b;a>=c;--a) 25 #define mem(a,b) memset(a,b,sizeof(a)) 26 #define pr printf 27 #define sc scanf 28 #define ls rt<<1 29 #define rs rt<<1|1 30 typedef long long ll; 31 void swapp(int &a,int &b); 32 double fabss(double a); 33 int maxx(int a,int b); 34 int minn(int a,int b); 35 int Del_bit_1(int n); 36 int lowbit(int n); 37 int abss(int a); 38 //const long long INF=(1LL<<60); 39 const double E=2.718281828; 40 const double PI=acos(-1.0); 41 const int inf=(1<<30); 42 const double ESP=1e-9; 43 const int mod=(int)1e9+7; 44 const int N=(int)1e6+10; 45 46 int n; 47 48 bool vis[N]; 49 vector<vector<int> >G(N); 50 struct node{int now,val;}; 51 void Init() 52 { 53 for(int i=1;i<=n;++i) 54 vis[i]=0; 55 } 56 int Val_bfs(node start) 57 { 58 int ans=0; 59 queue<node>q; 60 q.push(start); 61 while(!q.empty()) 62 { 63 node v=q.front();q.pop(); 64 ans=max(ans,v.val); 65 vis[v.now]=1; 66 int sz=G[v.now].size(); 67 for(int i=0;i<sz;++i) 68 { 69 int to=G[v.now][i]; 70 if(!vis[to]) 71 q.push({to,v.val+1}); 72 } 73 } 74 return ans; 75 } 76 77 int Start,End; 78 void queue_dfs1(node start) 79 { 80 Init(); 81 int max_=0; 82 queue<node>q; 83 q.push(start); 84 while(!q.empty()) 85 { 86 node v=q.front();q.pop(); 87 vis[v.now]=1; 88 if(max_<v.val)max_=v.val,Start=v.now; 89 int sz=G[v.now].size(); 90 for(int i=0;i<sz;++i) 91 { 92 int to=G[v.now][i]; 93 if(!vis[to]) 94 q.push({to,v.val+1}); 95 } 96 } 97 } 98 int fa[N]; 99 void queue_dfs2() 100 { 101 for(int i=1;i<=n;++i)fa[i]=0; 102 Init(); 103 int max_=0; 104 queue<node>q; 105 q.push({Start,1}); 106 while(!q.empty()) 107 { 108 node v=q.front();q.pop(); 109 vis[v.now]=1; 110 if(max_<v.val)max_=v.val,End=v.now; 111 int sz=G[v.now].size(); 112 for(int i=0;i<sz;++i) 113 { 114 int to=G[v.now][i]; 115 if(!vis[to]) 116 q.push({to,v.val+1}),fa[to]=v.now; 117 } 118 } 119 } 120 int Line[N]; 121 int get_line() 122 { 123 Init(); 124 int pos=End; 125 int cnt=0; 126 while(fa[pos]) 127 Line[++cnt]=pos,vis[Line[cnt]]=1,pos=fa[pos]; 128 Line[++cnt]=pos,vis[Line[cnt]]=1; 129 return cnt; 130 } 131 int Val[N]; 132 struct mark 133 { 134 int L,p1; 135 }memery[N],memery2[N]; 136 void solve(int cnt) 137 { 138 int p1; 139 for(int i=1;i<=cnt;++i) 140 Val[i]=Val_bfs({Line[i],0}); 141 memery[0]=memery2[cnt+1]={-1,-1}; 142 for(int i=1;i<=cnt-1;++i) 143 { 144 int lenth=(Val[i]+i+1)/2; 145 if((Val[i]+i)%2==0) 146 lenth++; 147 p1=Line[lenth]; 148 if(lenth<memery[i-1].L) 149 memery[i]=memery[i-1]; 150 else 151 memery[i]={lenth,p1}; 152 } 153 int p2; 154 for(int i=cnt;i>=2;--i) 155 { 156 int lenth=(Val[i]+cnt+1-i+1)/2; 157 if((Val[i]+cnt+1-i)%2==0) 158 lenth++; 159 p2=Line[cnt+1-lenth]; 160 if(lenth<memery2[i+1].L) 161 memery2[i]=memery2[i+1]; 162 else 163 memery2[i]={lenth,p2}; 164 } 165 int L=inf,P1,P2; 166 for(int i=1;i<=cnt-1;++i) 167 { 168 if(L>max(memery[i].L,memery2[i+1].L)) 169 L=max(memery[i].L,memery2[i+1].L),P1=memery[i].p1,P2=memery2[i+1].p1; 170 } 171 pr("%d %d %d\n",L-1,P1,P2); 172 } 173 174 int main() 175 { 176 // freopen("C:\\Users\\13606\\Desktop\\草稿.txt","r",stdin); 177 int T; 178 sc("%d",&T); 179 while(T--) 180 { 181 sc("%d",&n); 182 for(int i=1;i<=n;++i) 183 G[i].clear(); 184 for(int i=1;i<=n-1;++i) 185 { 186 int u,v; 187 sc("%d%d",&u,&v); 188 G[u].push_back(v); 189 G[v].push_back(u); 190 } 191 queue_dfs1({1,1}); 192 queue_dfs2(); 193 int lenth=get_line(); 194 solve(lenth); 195 } 196 return 0; 197 } 198 199 /**************************************************************************************/ 200 201 int maxx(int a,int b) 202 { 203 return a>b?a:b; 204 } 205 206 void swapp(int &a,int &b) 207 { 208 a^=b^=a^=b; 209 } 210 211 int lowbit(int n) 212 { 213 return n&(-n); 214 } 215 216 int Del_bit_1(int n) 217 { 218 return n&(n-1); 219 } 220 221 int abss(int a) 222 { 223 return a>0?a:-a; 224 } 225 226 double fabss(double a) 227 { 228 return a>0?a:-a; 229 } 230 231 int minn(int a,int b) 232 { 233 return a<b?a:b; 234 }