---
# System prepended metadata

title: Codeforces 1790 Timofey and Black-White Tree
tags: [codeforces, Tree]

---

# Codeforces 1790 Timofey and Black-White Tree
###### tags: `codeforces` `Tree`

[題目連結](https://codeforces.com/contest/1790/problem/F)

# 題目說明
給定一顆 N個節點的數, 起初有一個初始節點 c1 被染色

接下來 給 n-1個染色的節點, c2, c3, c4... cn

每次有新的染色節點時, 印出在這棵樹上任意兩個染色節點最短的距離.


ex:
![](https://i.imgur.com/cCpzJXh.png)
染色節點 1, 6 其距離為 3
染色節點 1, 4 其距離為 2
因此在這三個染色點, 最短的距離為 2

:::info
:bulb: **需要的知識**:
在一條長度為n的線段, 放置$\sqrt{n}$個節點, 兩兩之間的距離一定小於等於 $\sqrt{n}$

也就是說 距離最大的情況為 $\sqrt{n}$
![](https://i.imgur.com/mzZRcOT.png)


對於樹的結構, 也會有相同的特性,
在樹的節點, 擺放 $\sqrt{n}$ 的節點, 兩兩之間的距離一定小於等於 $\sqrt{n}$
:::


:::info
:bulb: 特性 1
假如當前任意兩個染色節點最短距離為 x,
新的點加入時,  該節點到達其他染色距離 只要大於等於 x, 
就表示該節點不會影響結果.
:::



# Method DFS
:::info
:bulb: **作法講解**:
變數說明:
min_dist: 維護其他染色節點到達 ith node 所需要的最短距離.
output: 維護當前加入節點的最短距離.


一開始先使用DFS 遍歷 c1 節點 到所有節點的距離, 

每次有新染節點(node)加入時, 
min_dist[node]的值就表示 node 到 其他最近的染色節點的距離.
更新 output = min(output, min_dist[node])

然後再從node出發, 遍歷node附近的節點, 這邊需要特別注意,
**case 1: 假如新的節點 x 與node 的距離 大於等於 min_dist[x], 表示前面有其他染色節點更靠近x.**
           
**case 2: 假如新的節點 x 與node 的距離 大於等於 output, 即使更新了其min_dist[x],**
**min_dist[x]對於最終結果也不會有影響**




:::

TC: O(NlogN) SC: O(N)

完整程式碼
```cpp=
int nums[N];
vector<int> adj[N];
int min_dist[N];
void dfs(int node, int parent, int d, int &ans)
{
    if ((d >= min_dist[node]) || (d >= ans)) {
        return;
    }
    min_dist[node] = d;
    for (int next : adj[node]) {
        if (next == parent) {
            continue;
        }
        dfs(next, node, d + 1, ans);
    }
}

void solve(int round)
{
    int n, c;
    int a, b;
    int output = INT32_MAX;

    for (int i = 0; i < N; i++) {
        adj[i].clear();
    }
    CLR(nums);
    SET(min_dist, 0x3f);

    cin >> n >> c;

    for (int i = 1; i < n; i++) {
        cin >> nums[i];
    }

    for (int i = 0; i < n-1; i++) {
        cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }

    dfs(c, -1, 0, output);

    for (int i = 1; i < n; i++) {
        output = min(output, min_dist[nums[i]]);
        printf("%d ", output);
        dfs(nums[i], -1, 0, output);
    }
    printf("\n");
}
```



