1. 程式人生 > >HDU 6228 - Tree - [DFS]

HDU 6228 - Tree - [DFS]

targe equal sig ont 當前 ref led 題目 input

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6228

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)

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

Source
2017ACM/ICPC亞洲區沈陽站-重現賽(感謝東北大學)

題意:

一顆無根樹,有 $n$ 個節點,現在要給每個節點上 $k$ 種顏色中的一種,

然後對於第 $i$ 種顏色的所有節點,$E_i$ 是連接這些節點所需要的最少的邊的集合;

要求最大的 $\left| {E_1 \cap E_2 \cap \cdots \cap E_{k - 1} \cap E_k } \right|$。

題解:

考慮對於任意一條邊,把它的左側節點 $u$ 看做統領一棵樹,右側節點 $v$ 也統領一棵樹,兩棵樹的樹根被當前這條邊連接起來,

那麽,不難想象,兩側樹的節點數目均不小於 $k$ 是當前邊作為“答案集”的一個元素的必要條件

(不過,我不知道怎麽證明是充分條件,不過想來必然存在一種上色方案,使得上述必要條件成為充分條件),

那麽,可以使用DFS遍歷整棵樹,對於遍歷到的任意一條邊,假設它連接到的子節點 $v$ 所統領的整棵子樹的數目為 $cnt[v]$,

那麽,只要滿足 $cnt[v] \ge k$ 且 $n - cnt[v] \ge k$,當前這條邊就算做“答案集”的一個元素,$ans++$;

最後,DFS結束,輸出 $ans$ 即可。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=150000+10;

int n,k;
int ans;

struct Edge{
    int u,v;
    Edge(int u=0,int v=0){this->u=u,this->v=v;}
};
vector<Edge> E;
vector<int> G[maxn];
void init(int l,int r)
{
    E.clear();
    for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int u,int v)
{
    E.push_back(Edge(u,v));
    G[u].push_back(E.size()-1);
}

int vis[maxn];
int dfs(int now)
{
    vis[now]=1;
    int tot=1;
    for(int i=0;i<G[now].size();i++)
    {
        Edge &e=E[G[now][i]]; int nxt=e.v;
        if(!vis[nxt]) tot+=dfs(nxt);
    }
    if(n-tot>=k && tot>=k) ans++;
    return tot;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%d%d",&n,&k);
        init(1,n);
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }

        memset(vis,0,sizeof(vis));
        ans=0;
        dfs(1);
        cout<<ans<<endl;
    }
}

HDU 6228 - Tree - [DFS]