hdu 6228

来源:互联网 发布:网络光端机是什么 编辑:程序博客网 时间:2024/05/22 09:35

Tree

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 531 Accepted Submission(s): 338

Problem Description
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

题意:给一个数,k种颜色,让你给这个树染色,如果一个边的两边的点都含有k种颜色,那么这条边是好边,求可以得到的最多的好边的数量。
做法:以任意一个点为根,拿掉任意一个边会得到两个子树,如果这两个子树的节点数都大于等于k那么这条边就是好边,然后枚举每一条边就可以得到答案了。
做法2:有点像是无向图的反拓扑序,对于每一个点保存两个值,sz[i],代表第i个点还连有多少个点,col[i],第i个点最少一边有多少个点,每次把sz[i]==1,clo[i] < k的点放进队列,进入队列的点都是坏点,然后剩余的点都是好点,好点的定义是好点跟好点的连线一定是好边,然后答案就是好点的数量-1.

#include<bits/stdc++.h>using namespace std;int T,n,k;const int N = 2e5+100;vector<int> G[N];int son[N],fa[N];int ans = 0;void dfs(int u,int f){    fa[u] = f;    son[u] = 1;    for(int i = 0;i < G[u].size();i ++){        int v = G[u][i];        if(v == f) continue;        dfs(v,u);        son[u] += son[v];    }}int main(){    cin >> T;    while(T--){        ans = 0;        scanf("%d %d",&n,&k);        for(int i = 1;i <= n;i ++) G[i].clear();        for(int i = 1;i < n;i ++){            int u,v;            scanf("%d %d",&u,&v);            G[u].push_back(v);            G[v].push_back(u);        }        dfs(1,-1);        for(int i = 1;i <= n;i ++){            for(int j = 0;j < G[i].size();j ++){                int v = G[i][j];                if(i == fa[v]){                    if(son[v] >= k && n >= son[v]+k) ans ++;                }            }        }        cout << ans << endl;    }    return 0;}
#include<bits/stdc++.h>using namespace std;const int N = 2e5+100;vector<int> G[N];int sz[N];int clo[N];int T,n,k;int main(){    cin >> T;    while(T--){        scanf("%d %d",&n,&k);        for(int i = 1;i <= n;i ++) G[i].clear(),sz[i] = 0,clo[i] = 1;        for(int i = 1;i < n;i ++){            int u,v;            scanf("%d %d",&u,&v);            G[u].push_back(v);            G[v].push_back(u);            sz[u]++;            sz[v]++;        }        queue<int> que;        for(int i = 1;i <= n;i ++)if(sz[i] == 1&&k!= 1)que.push(i),sz[i] = 0;        int cnt = 0;        while(!que.empty()){            int now = que.front();            cnt ++;            que.pop();            for(int i = 0;i < G[now].size();i ++){                int v = G[now][i];                if(sz[v]){                    clo[v] += clo[now];                    sz[v] --;                    if(sz[v] == 1&&clo[v] < k){                        que.push(v);                        sz[v] = 0;                    }                }            }        }        int ans = n-cnt;        if(ans) ans --;        cout << ans << endl;    }    return 0;}
原创粉丝点击