题意:给定一棵树,设A, B, C为树上的三个不相同的点,求出max{dist(A, B) + min{dist(C, A), dist(C, B)}}
首先,如果dist(A,B)最大的话,很显然这是树上的一条最长链。也就是说,A和B是树上任意一条最长链的两个端点。
然后,我们有一个结论:树上某个点的最远点必定是树上任意一条最长链的两个端点中的一个。。
综合上面两个结论我们可以得到,当dist(A, B)和min{dist(C, A), dist(C, B)}同时取最大时,都与树上的最长链有关。。
毫不犹豫的求出最长链,并记录下它的两个端点A和B。然后枚举点C就可以啦~
求最长链的时间复杂度是O(N),求出A和B到每个点的距离的时间复杂度是O(N),枚举C的时间复杂度是O(N)。。因此总的时间复杂度就是O(N)
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 6 using namespace std; 7 8 const size_t Max_N(200050); 9 const size_t Max_M(400050); 10 11 size_t N; 12 13 unsigned int Total; 14 unsigned int Head[Max_N]; 15 unsigned int To[Max_M]; 16 unsigned long long int Weight[Max_M]; 17 unsigned int Next[Max_M]; 18 19 inline 20 unsigned long long int Max(const unsigned long long int &a, const unsigned long long int &b) 21 { 22 return a > b ? a : b; 23 } 24 25 inline 26 unsigned long long int Min(const unsigned long long int &a, const unsigned long long int &b) 27 { 28 return a < b ? a : b; 29 } 30 31 inline 32 void Add_Edge(const size_t &s, const size_t &t, const unsigned long long int &w) 33 { 34 ++Total, To[Total] = t, Weight[Total] = w, Next[Total] = Head[s], Head[s] = Total; 35 } 36 37 void init() 38 { 39 unsigned int M; 40 size_t u, v; 41 unsigned long long int w; 42 43 cin >> N >> M; 44 while (M--) 45 { 46 cin >> u >> v >> w; 47 Add_Edge(u, v, w); 48 Add_Edge(v, u, w); 49 } 50 } 51 52 struct node 53 { 54 node(const unsigned int &a = 0, const unsigned long long int &b = 0) : now(a), wsum(b) {} 55 unsigned int now; 56 unsigned long long int wsum; 57 }; 58 59 size_t A, B;//树上最长链的两个端点 60 61 unsigned long long int Dist_A[Max_N], Dist_B[Max_N]; 62 //分别存储A到各个点的距离和B到各个点的距离 63 64 unsigned long long int Now_Max; 65 bool In_Q[Max_N]; 66 67 void BFS_1() 68 { 69 Now_Max = 0ULL; 70 queue<node> Q; 71 Q.push(node(1, 0ULL)); 72 In_Q[1] = true; 73 node Top; 74 while (Q.size()) 75 { 76 Top = Q.front(); 77 Q.pop(); 78 if (Top.wsum > Now_Max) 79 { 80 Now_Max = Top.wsum; 81 A = Top.now; 82 } 83 for (size_t i = Head[Top.now];i;i = Next[i]) 84 if (!In_Q[To[i]]) 85 { 86 In_Q[To[i]] = true; 87 Q.push(node(To[i], Top.wsum + Weight[i])); 88 } 89 } 90 } 91 92 void BFS_2() 93 { 94 Now_Max = 0ULL; 95 memset(In_Q, false, sizeof(In_Q)); 96 queue<node> Q; 97 Q.push(node(A, 0ULL)); 98 In_Q[A] = true; 99 node Top; 100 while (Q.size()) 101 { 102 Top = Q.front(); 103 Q.pop(); 104 if (Top.wsum > Now_Max) 105 { 106 Now_Max = Top.wsum; 107 B = Top.now; 108 } 109 for (size_t i = Head[Top.now];i;i = Next[i]) 110 if (!In_Q[To[i]]) 111 { 112 In_Q[To[i]] = true; 113 Q.push(node(To[i], Top.wsum + Weight[i])); 114 } 115 } 116 } 117 118 void BFS_A()//求出A到各个点的距离 119 { 120 memset(In_Q, false, sizeof(In_Q)); 121 queue<unsigned int> Q; 122 Q.push(A); 123 In_Q[A] = true; 124 unsigned int Top; 125 while (Q.size()) 126 { 127 Top = Q.front(); 128 Q.pop(); 129 for (size_t i = Head[Top];i;i = Next[i]) 130 if (!In_Q[To[i]]) 131 { 132 In_Q[To[i]] = true; 133 Q.push(To[i]); 134 Dist_A[To[i]] = Dist_A[Top] + Weight[i]; 135 } 136 } 137 } 138 139 void BFS_B()//求出B到各个点的距离 140 { 141 memset(In_Q, false, sizeof(In_Q)); 142 queue<unsigned int> Q; 143 Q.push(B); 144 In_Q[B] = true; 145 unsigned int Top; 146 while (Q.size()) 147 { 148 Top = Q.front(); 149 Q.pop(); 150 for (size_t i = Head[Top];i;i = Next[i]) 151 if (!In_Q[To[i]]) 152 { 153 In_Q[To[i]] = true; 154 Q.push(To[i]); 155 Dist_B[To[i]] = Dist_B[Top] + Weight[i]; 156 } 157 } 158 } 159 160 void Longest_Path()//求出最长链相关信息 161 { 162 BFS_1(); 163 BFS_2(); 164 BFS_A(); 165 BFS_B(); 166 } 167 168 void Get_Ans() 169 { 170 unsigned long long int Ans(0ULL); 171 for (size_t i = 1;i <= N;++i) 172 Ans = Max(Ans, Now_Max + Min(Dist_A[i], Dist_B[i])); 173 cout << Ans << endl; 174 } 175 176 int main() 177 { 178 init(); 179 180 Longest_Path(); 181 182 Get_Ans(); 183 184 return 0; 185 }
BZOJ 1509
时间: 2024-10-16 04:04:03