Tree(HDU - 6228)

本文探讨了一道关于树结构的图论问题,即给定一棵包含n个顶点的树,使用k种颜色对顶点进行染色,求不同颜色最小生成树的边最大交集数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Consider a un-rooted tree T which is not the biological significance of tree or plant, but a tree as an undirected graph in graph theory with n nodes, labelled from 1 to n. If you cannot understand the concept of a tree here, please omit this problem.
Now we decide to colour its nodes with k distinct colours, labelled from 1 to k. Then for each colour i = 1, 2, · · · , k, define Ei as the minimum subset of edges connecting all nodes coloured by i. If there is no node of the tree coloured by a specified colour i, Ei will be empty.
Try to decide a colour scheme to maximize the size of E1 ∩ E2 · · · ∩ Ek, and output its size.

Input

The first line of input contains an integer T (1 ≤ T ≤ 1000), indicating the total number of test cases.
For each case, the first line contains two positive integers n which is the size of the tree and k (k ≤ 500) which is the number of colours. Each of the following n - 1 lines contains two integers x and y describing an edge between them. We are sure that the given graph is a tree.
The summation of n in input is smaller than or equal to 200000.

Output

For each test case, output the maximum size of E1 ∩ E1 … ∩ Ek.

Sample Input

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

Sample Output

1
0
1

题意:

给出一棵n个顶点的树,树上的点必须用k种颜色进行上色。求各种颜色的最小生成树的边的最大交集的数量。

思路:

题意有点难懂,队友看完题后告诉我,当一条边的两端都至少有k个顶点时,这条边肯定是交集中的边,我花了几个图好像也确实是这样,就想着先写一下试试看。
直接从叶子开始向上深搜,可以搜出每个点一边的点数a,那么由于是一棵树,那么另一边的顶点数就是n-a。接着枚举所有点,就可以得出答案。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
#define S_1(x) scan_d(x)
#define S_2(x,y) scan_d(x),scan_d(y)
#define S_3(x,y,z) scan_d(x),scan_d(y),scan_d(z)
#define sf_1(x) scan_lf(x)
#define sf_2(x, y) scan_lf(x), scan_lf(y)
#define sf_3(x, y, z) scan_lf(x), scan_lf(y), scan_lf(z)
#define sf_4(x, y, z, X) scan_lf(x), scan_lf(y), scan_lf(z), scan_lf(X)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back
typedef long long LL;
typedef unsigned long long ull;
typedef unsigned long long int ulli;
typedef pair <int, int> ii;
const int INF = 0x3f3f3f3f;
const LL LINF = 0x3f3f3f3f3f3f3f3fLL;
const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1};
const int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
const int maxn = 2e5 + 10;
const int maxx = 2e5 + 10;
const double EPS = 1e-8;
const double eps = 1e-10;
const int mod = 1e9 + 7;
const int MOD = 1e3;
template <class T> inline T min(T a, T b, T c) {return min(min(a, b), c);}
template <class T> inline T max(T a, T b, T c) {return max(max(a, b), c);}
template <class T> inline T min(T a, T b, T c, T d) {return min(min(a, b), min(c, d));}
template <class T> inline T max(T a, T b, T c, T d) {return max(max(a, b), max(c, d));}
template <class T> inline bool scan_d(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return 0;
    W (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
    W (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
inline bool scan_lf(double &num) {
    char in;
    double Dec = 0.1;
    bool IsN = false, IsD = false;
    in = getchar();
    if (in == EOF) return false;
    W (in != '-' && in != '.' && (in < '0' || in > '9')) in = getchar();
    if (in == '-') {IsN = true; num = 0;}
    else if (in == '.') {IsD = true; num = 0;}
    else num = in - '0';
    if (!IsD) {
        W (in = getchar(), in >= '0' && in <= '9') {num *= 10; num += in - '0';}
    }
    if (in != '.') {
        if (IsN) num = -num;
        return true;
    }
    else{
        W (in = getchar(), in >= '0' && in <= '9') {
            num += Dec * (in - '0');
            Dec *= 0.1;
        }
    }
    if (IsN) num = num;
    return true;
}
void Out(LL a) {if(a < 0) {putchar('-'); a = -a;}if(a >= 10) Out(a / 10); putchar(a % 10 + '0');}
void print(LL a) {Out(a), puts("");}
/**********************************************WHITE_YASHA**********************************************/
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
struct edge {
    int to, next;
    edge(int _to, int _next) {
        to = _to;
        next = _next;
    }
    edge() {}
} edges[maxx];
int head[maxx], tot, cnt[maxn];
int t, n, k;
void add_edge(int u, int v) {
    edges[tot] = {v, head[u]};
    head[u] = tot++;
}
void init() {
    me(head, -1);
    FOR (1, n, i) cnt[i] = 1;
    tot = 0;
    me(edges, 0);
}
void dfs(int x) {
    for (int i = head[x]; i != -1; i = edges[i].next) {
        int v = edges[i].to;
        dfs(v);
        cnt[x] += cnt[v];
    }
}
int main() {
    s_1(t);
    W (t--) {
        s_2(n, k);
        init();
        int u, v;
        FOr (0, n - 1, i) {
            s_2(u, v);
            add_edge(u, v);
        }
        dfs(1);
        int res = 0;
        FOR (1, n, i) if (cnt[i] >= k && n - cnt[i] >= k) res++;
        printf("%d\n", res);
    }
}
//
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值