Dotted rule - Getting Started Learning Notes

Foreword

  Just finished learning the basics of partition points, finished a template question then write about the next thing to understand the learning.

text

  The main idea of ​​divide and conquer is a main issue for the decomposition of a problem child, and the child has a problem with the main problems of the same nature and the same question after the answer to the main question of the various sub-merged. The point is to partition tree by selecting a point of splitting, the answer process by recursive sub-tree.

  Select the partition points (points)

    If a tree at a point divided into multiple sub trees, and the same sub-tree split operation, then obviously each individual tree is split into subtrees same size is more possible priority. If that happens to be a chain of a tree, then compared step by step from the end of the chain splitting, must be split at a time from the intermediate frequency is relatively small. So every time the maximum size of the subtrees influence split point and the minimum point of the largest subtree of a tree exactly a name, called the center of gravity of the tree.

  Deal with the problem (rule)

    How is the processing of a problem after the problem tree split solved, here to POJ-1741 (template title) http://poj.org/problem?id=1741 described as an example (qwq too weak (⊙ = ⊙)). Title required number of points in the tree, the distance between two points is less than or equal to K.

    The results for this problem is not divided through the center of gravity and the center of gravity for each processing pass. This way, then we processed passes through the center of gravity of the answer, they can be taken off point, then do not go through the center of gravity of the answers will be used only in the sub-tree processing before it. One thing to note is the result of the focus of the answer may come from a sub-tree, the center of gravity to the sub-tree of some of the edges may be counted twice, does not meet the requirements, then this number can not be calculated into the final answer. So this time we need to look at the inclusion-exclusion, the subtree minus the answer on the line.

Code

  

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <queue>
#include <stack>
#include <map>
#define ull unsigned long long
#define met(a, b) memset(a, b, sizeof(a))
#define lowbit(x) (x&(-x))
#define MID (l + r) / 2
#define ll long long
#define cinint(a) scanf("%d", &a)
#define cinll(a) scanf("%lld", &a)
#define cindouble(a) scanf("%lf", &a)
#define cinstr(a) scanf(" %s", a)
#define coutint(a) printf("%d\n", a)
#define coutll(a) printf("%lld\n", a)
#define coutdouble(a) printf("%lf\n", a)

using namespace std;

const int maxn = 1e4 + 7;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
//前向星存图
struct Edge { ll to, dist, net; }MAP[maxn*2]; head LL [MAXN], CNT;
//
LL Dist [MAXN]; // record the depth of each point ll arr [maxn], tail; // record the operator answers in various depths ll sz [maxn], msz [ maxn] , all, rt; // subtrees are used as a recording size of each dot, the maximum size of each point of the sub-tree, the total size of the sub-tree, the position of the center of gravity
BOOL VIS [MAXN]; // record whether the points are taken off ll n, K;   LL RES; // final answer void the init () { for (LL I = . 1 ; I <= n-; I ++ ) { head [I] = - . 1 ; VIS [I] = 0 ; } RT = CNT = RES = 0 ; MSZ [RT] = INF; All = n-; } void addMAP(ll u, ll v, ll c) { MAP[cnt] = (Edge){v, c, head[u]}; head[u] = cnt++; }
//寻找重心位置
void Findrt(ll pos, ll pre) { sz[pos] = 1; msz[pos] = 1; for(ll i = head[pos]; i != -1; i = MAP[i].net) { ll to = MAP[i].to; if(vis[to] || to == pre) continue; Findrt(to, pos); sz[pos] += sz[to]; msz[pos] =max (SZ [to], MSZ [POS]); } MSZ [POS] = max (All - SZ [POS], MSZ [POS]); // Note removed subtree below, can be considered incoming direction subtree if (MSZ [POS] <MSZ [RT] || RT == 0 ) = RT POS; // minimum maximum claim subtree }
// calculated for each time point to the current point to the root depth
void getdist (POS LL, LL pre ) { ARR [ ++ tail] = Dist [POS]; for (I = LL head [POS]; I = -! . 1 ; I = the MAP [I] .NET) { LL to = the MAP [I] .to; IF (VIS || to pre == [to]) Continue ; Dist [to] = Dist [POS] + the MAP [I] .dist; } getdist (to, POS); } LL CON (LL POS, LL dist) { Dist [POS] = dist; tail = 0 ; LL SUM = 0 ; getdist (POS, 0 ); Sort (ARR + . 1 , ARR + . 1 + tail); LL L = . 1 , R & lt = tail; the while (L < R & lt) { the while (L <R & lt && ARR [L] + ARR [R & lt]> K) r-- ; // required distance between two points less subject K, is two to from the root node equal to the sum is less than K SUM + = R & lt - L; L ++ ; } returnSUM; } LL Spot_Divide_Conquer (LL POS) { Findrt (POS, 0 ); // for every process to find the center of gravity tree rt VIS [rt] = . 1 ; // center of gravity rt pluck RES + = CON (rt, 0 ); // CON function calculation of the answers through the bit Congratulations for (I = LL head [RT]; I = -! . 1 ; I = the MAP [I] .NET) { LL to = the MAP [I] .to ; IF (VIS [to]) the Continue ;
// subtract each sub-tree impact on the answers of All
= sz [to];   RT = 0 ; RES - = CON (to, MAP [i] .dist);
// Spot_Divide_Conquer(to); } }
int main() { while(1) { cinll(n); cinll(k); if(!n && !k) break; init(); for(ll i = 1; i < n; i++) { ll u, v, c; cinll(u); cinll(v); cinll(c); addMAP(u, v, c); addMAP(v, u, c); } Spot_Divide_Conquer(1); coutll(res); } return 0; }

 

Guess you like

Origin www.cnblogs.com/Stay-Online/p/11305561.html