Acwing 252. 树
生活随笔
收集整理的這篇文章主要介紹了
Acwing 252. 树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Acwing 252. 樹
題意:
給定一個有 N 個點(編號 0,1,…,N?1)的樹,每條邊都有一個權值(不超過 1000)。
樹上兩個節點 x 與 y 之間的路徑長度就是路徑上各條邊的權值之和。
求長度不超過 K 的路徑有多少條。
1≤N≤104,
1≤K≤5×106,
0≤l≤103
題解:
P4178 Tree,和這個題題意是一樣的,但是本題的數據范圍更大,本題k<=5e6,且空間只給了10MB,樹狀數組的方法是不行,需要用容斥
我們cal直接記錄以u為出發點的所有路徑長度,用數組d來存,對數組d排序,然后利用尺取的方法來確定有多少對長度之和小于k。但是這樣是會造成重復的
對于圖中綠色兩點,其路徑應該是紫色線,但是我們在計算u時會將紅色部分也計算進去,因此我們要將多余部分刪去,對于u的兒子節點v,我們計算一遍以v為出發點的路徑(還要額外加上邊長dis(u,v) ),有多少對長度之和小于k,相當于綠線部分,然后減去綠線部分,相當于將多余部分刪去
代碼:
#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef LOCALstartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef LOCALendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn= 1e5 + 9; int n, k; vector<PII> vec[maxn]; int vis[maxn]; int rt, cnt; int sz[maxn], d[maxn]; void dfs_rt(int u, int fa, int tot) {sz[u]= 1;int maxx= 0;for (auto it : vec[u]) {int v= it.first;int w= it.second;if (v == fa || vis[v])continue;dfs_rt(v, u, tot);sz[u]+= sz[v];maxx= max(maxx, sz[v]);}maxx= max(maxx, tot - sz[u]);if (2 * maxx <= tot)rt= u; } void dfs_dis(int u, int fa, int dis) {d[++cnt]= dis; //記錄了所有路徑長度for (auto it : vec[u]) {int v= it.first;int w= it.second;if (v == fa || vis[v])continue;dfs_dis(v, u, dis + w);} } int calc(int u, int w) {cnt= 0;dfs_dis(u, 0, w);sort(d + 1, d + 1 + cnt);int l= 1, r= cnt, ans= 0;while (l < r) {while (d[l] + d[r] > k && l < r)r--;/*d是遞增的,當d[l]+d[r]<=k時,此后所有r到l這段都是小于k的*/ans+= (r - l);l++;}return ans; } int solve(int u, int fa, int tot) {dfs_rt(u, fa, tot);u= rt;vis[u]= 1;int res= calc(u, 0);for (auto it : vec[u]) {int v= it.first;int w= it.second;if (vis[v])continue;res-= calc(v, w);res+= solve(v, u, cnt);}return res; } int main() {//rd_test();while (1) {read(n, k);if (!n && !k)break;for (int i= 1; i <= n; i++)vec[i].clear();for (int i= 1; i <= n; i++)vis[i]= 0;int u, v, w;for (int i= 1; i < n; i++) {read(u, v, w);u++;v++;vec[u].push_back({v, w});vec[v].push_back({u, w});}printf("%d\n", solve(1, 0, n));}return 0;//Time_test(); }總結
以上是生活随笔為你收集整理的Acwing 252. 树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 炫龙毁灭者安装ubuntu18.04.1
- 下一篇: P4149 [IOI2011]Race