MENU

Solution. CF1710D Recover the Tree

Description

根据以下信息构造一棵树:

  • 树的节点个数为 $n$,编号为 $1\sim n$。
  • 对于每个编号区间 $[l,r]$ 给出是否构成连通块。

$n\le 2000$

Solution

难得做出了 3400 的构造,很有意思的题目。

从小到大考虑每个好区间。

当 $r=l+1$ 时,如果构成连通块,则必然有 $l\to l+1$ 的连边。

对于长度为 $d$ 的好区间 $[l,r]$,此时所有长度 $<d$ 的好区间都已经满足题意,首先由于我们的构造方式,所有的连通块都是区间。假如 $l,r$ 处于不同的连通块,我们会连一条 $l\to r$ 的边将两个连通块合并,注意此时在 $l,r$ 所在的连通块之间还可能存在一些散块,我断言散块的数量不可能为 $1$,否则显然无解,既然散块的数量大于 $1$,容易想到构造左往右连、右往左连这样的交叉连边,这样如果不同时包含 $l,r$,任取若干散块,他们仍然不连通,于是就保证了不会破坏较小区间的正确性。

实现细节略去,代码十分易懂。

值得一提的是,枚举所有好区间的复杂度是 $\mathcal O(n^2)$,而对于每个尚未连通的好区间,我们都暴力遍历了区间中的每个点检查连通性,尽管如此,由于每次暴力遍历都至少会连一条边,而树上的总边数是 $n-1$,故总复杂度是正确的 $\mathcal O(n^2)$。

Code

namespace Main{
    const int N = 2005;
    int t, n, fa[N];
    char con[N][N];
    int get(int x){
        if(fa[x] == x) return x;
        return fa[x] = get(fa[x]);
    }
    void unite(int x, int y){
        fa[get(x)] = get(y);
    }
    void Main(){
        input(t);
        while(t--){
            input(n);
            for(int i = 1; i <= n; i++) scanf("%s", con[i] + 1);
            for(int i = 1; i <= n; i++) fa[i] = i;
            for(int i = 2; i <= n; i++){
                for(int j = 1; j + i - 1 <= n; j++){
                    int k = j + i - 1;
                    if(con[j][i] != '1' || get(j) == get(k)) continue;
                    unite(j, k);
                    write(j), putchar(' '), write(k), puts("");
                    bool fir = true;
                    for(int p = j + 1; p < k; p++){
                        if(get(p) != get(j)){
                            if(fir){
                                write(p), putchar(' '), write(k), puts("");
                                unite(p, k);
                                fir = false;
                            }
                            else{
                                write(p), putchar(' '), write(j), puts("");
                                unite(p, j);
                            }
                        }
                    }
                }
            }
        }
        return;
    }
}
Last Modified: October 7, 2022
Archives Tip
QR Code for this page
Tipping QR Code