1. 程式人生 > >6228 Tree

6228 Tree

Tree 題 意:給你n個節點的一顆樹,用k種顏色染色,求一個最小的邊的Ei集合,Ei代表一個最小的邊集連線所有節點顏色為i的集合。 資料範圍: 1<=T<=1e41<=T<=1e4 1<=k<=5001<=k<=500 n最多不超過2e52e5 輸入樣例:

3
4 2
1 2
2 3
3 4
4 2
1 2
1 3
1 4
6 3
1 2
2 3
3 4
3 5
6 2

輸出樣例:

1
0
1

思維題樹型題的套路:無根樹先轉化成有根樹試一試,可能是每個節點的兒子節點個數,啥啥啥的。可以往這方面想一想。主要還是要去分析拉,看具體題目。邊轉化成點也是一個常用的套路

思 路:這就是一個思維題。先把無根樹轉化成有跟樹,對於一個邊,他只有兩個情況,要不在最後的答案集合,要不不在,我們只考慮在最後的答案集合裡面的。對於一條邊在最後集合裡面的,那麼他一定被染色k次以上,我們可以對點染色,如果一個條邊被染色k次以上,那麼他兩端的點也一定也被染色k次以上。 現在是一顆樹,一個節點可以被染色至少k次以上,如果他的(包含他自己)子節點的個數sz[i]>=k個 並且如果n-sz[i]>=k就代表該節點和他父節點邊可以被覆蓋次數>=k次。所以這題就很簡單了,只要dfs維護一下每個節點子節點個數就好了

如果有對你有幫助,點個贊哦~~O(∩_∩)O 如果有問題請留言哈!

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<queue>
#include<cmath>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<11
#define IN freopen("input.txt"
,"r",stdin) #define mst(x,y) memset(x,y,sizeof(x)); #define debug(x) cout<< #x <<" = "<< (x) <<endl; #define min(x,y) x>y?y:x #define max(x,y) x>y?x:y using namespace std; typedef long long ll; typedef pair<int,int> P; typedef unsigned long long ull; const int mod = 1e6+3; const int INF = 0x3f3f3f3f; const int LINF = 0x3f3f3f3f3f3f3f3f; const int maxn = 2e5+5; vector<int> G[maxn]; int sz[maxn]; int n,m; void dfs(int s,int fa){ sz[s] = 1; for(int i=0;i<G[s].size();i++){ int to = G[s][i]; if(to == fa)continue; dfs(to,s); sz[s]+=sz[to]; } } int main() { //IN; int t; scanf("%d",&t); while(t--){ scanf("%d %d",&n,&m); for(int i=0;i<=n;i++) G[i].clear(); mst(sz,0); for(int i=1;i<=n-1;i++){ int u,v; scanf("%d %d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); int ans = 0; for(int i=1;i<=n;i++){ if(sz[i]>=m && n-sz[i]>=m)ans++; } printf("%d\n",ans); } return 0; }