1. 程式人生 > >CodeForces 1042 F Leaf Sets 貪心

CodeForces 1042 F Leaf Sets 貪心

pri tor 需要 中一 2個 mes 地方 none http

Leaf Sets

題意:給你一棵樹,樹上有n個點,只有一條邊的點叫做葉子,現在要求把所有的葉子分組,每個組內的所有葉子的距離都不能大於k。

題解:

我們可以隨意找一個不是葉子的節點當做這顆樹的根節點,這樣這棵樹中葉子就不會出現在上方了,現在我們先把所有的葉子都單獨當做一個集合來。

假設現在我們在處理以u為根的這個子樹信息, 我們可以得到u子樹內的葉子都到u的這個地方的信息,對這些信息來說,我們把距離都sort一遍,然後看一下是不是能合並,能合並就把信息合並一下,然後在把u的信息記為 min ( 所有集合 max(合並過的)) 的信息。

也就是說每次都是將距離未合並的最小的那個鏈信息往上傳, 因為假如 u 這裏存在2個節點 d1 d2 , di和d2是沒有辦法合並的, 現在有一個 x 可以同時滿足 x 和 d1 合並 x 和 d2 合並, 但是我們也只能和其中一個合並。 所以我們實際上也只需要每次都往上傳一個信息就好了,為了更滿足合並的條件,我們當然要往上傳最容易合法的那個, 也就是在這一層合並完之後,最小的 合並內的最大值。

實際上就是貪心,能合並就合並。

代碼:

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define
lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = (int)1e9+7; const int N = 1e6 + 100; vector<int> vc[N], g; int n, m, h[N], ans = 0
; void dfs(int o, int u){ for(auto v : vc[u]){ if(v == o) continue; dfs(u, v); } if(vc[u].size() == 1) { h[u] = 1; return ; } g.clear(); for(auto v : vc[u]){ if(v == o) continue; g.pb(h[v]); } sort(g.begin(), g.end()); int p = 0; for(int i = 1; i < g.size(); ++i) if(g[i]+g[i-1] <= m) { ans--; p = i; } h[u] = g[p]+1; } int main(){ scanf("%d%d", &n, &m); for(int i = 1, u, v; i < n; ++i){ scanf("%d%d", &u, &v); vc[u].pb(v); vc[v].pb(u); } if(n == 2) puts("1"); else { ans = 0; int f = 1; for(int i = 1; i <= n; ++i){ if(vc[i].size() == 1) ans++; if(f && vc[i].size() > 1){ dfs(0, i); f = 0; } } printf("%d\n", ans); } return 0; }
View Code

CodeForces 1042 F Leaf Sets 貪心