首页 > 其他分享 >G. Penacony

G. Penacony

时间:2024-07-27 17:20:52浏览次数:14  
标签:10 路径 house Penacony leq roads rightarrow

G. Penacony

On Penacony, The Land of the Dreams, there exists $n$ houses and $n$ roads. There exists a road between house $i$ and $i+1$ for all $1 \leq i \leq n-1$ and a road between house $n$ and house $1$. All roads are bidirectional. However, due to the crisis on Penacony, the overseeing family has gone into debt and may not be able to maintain all roads.

There are $m$ pairs of friendships between the residents of Penacony. If the resident living in house $a$ is friends with the resident living in house $b$, there must be a path between houses $a$ and $b$ through maintained roads.

What is the minimum number of roads that must be maintained?

Input

The first line contains $t$ ($1 \leq t \leq 10^4$) – the number of test cases.

The first line of each test case contains two integers $n$ and $m$ ($3 \leq n \leq 2 \cdot 10^5, 1 \leq m \leq 2 \cdot 10^5$) – the number of houses and the number of friendships.

The next $m$ lines contain two integers $a$ and $b$ ($1 \leq a < b \leq n$) – the resident in house $a$ is friends with the resident in house $b$. It is guaranteed all ($a, b$) are distinct.

It is guaranteed the sum of $n$ and $m$ over all test cases does not exceed $2 \cdot 10^5$.

Output

For each test case, output an integer, the minimum number of roads that must be maintained.

Example

Input

7
8 3
1 8
2 7
4 5
13 4
1 13
2 12
3 11
4 10
10 2
2 3
3 4
10 4
3 8
5 10
2 10
4 10
4 1
1 3
5 2
3 5
1 4
5 2
2 5
1 3

Output

4
7
2
7
2
3
3

Note

For the first test case, the following roads must be maintained:

  • $8 \leftarrow \rightarrow 1$
  • $7 \leftarrow \rightarrow 8$
  • $1 \leftarrow \rightarrow 2$
  • $4 \leftarrow \rightarrow 5$

 

解题思路

  对于关系 $(a,b)$,最优路径必然是 $a \rightarrow a+1 \rightarrow \dots \rightarrow b$(记为路径 $1$)或 $a \rightarrow a-1 \rightarrow 1 \rightarrow n \rightarrow  \dots \rightarrow b$(记为路径 $2$)。这两条路径没有交集,且并集恰好是整个环。

  接着有个关键的性质:最优答案必然小于 $n$。反证法,假设最终选择了整个环的 $n$ 条边,现在任选一条边删除,如果某对关系的路径包含这条边,由上述知道必然可以换成该路径的补集。因此在最优解中必然至少有一条边不会被选。为此我们可以枚举每一条边作为不被选择的边。

  容易知道在删除环上的一条边后,每对关系的路径都会唯一确定。定义第 $i$ 条边表示连接点 $i$ 和 $i+1$ 之间的边,那么在删除第 $i$ 条边后,如果关系 $(a,b)$ 满足 $a \leq i < b$,则最优路径就是路径 $2$,否则为路径 $1$。显然我们可以枚举每条被删除的边,然后再枚举每对关系把路径标记出来,最后统计被标记的边的数量,取最小值,时间复杂度为 $O(nm)$。

  实际上如果从小到大枚举 $i$,当删除第 $i$ 条边时,只有 $a=i$(从路径 $1$ 变路径 $2$)和 $b=i$(从路径 $2$ 变路径 $1$)的关系的路径会受到影响,因此整个过程中只会改变 $2m$ 次路径。如果要标记路径 $1$,则可以对区间 $[a,b)$ 进行 $\pm 1$;如果要标记路径 $2$,则分别对区间 $[1,a)$ 和 $[b,n]$ 进行 $\pm 1$。最后查询的是区间 $[1,n]$ 中有标记的长度总和。【模板】扫描线的线段树可以实现该功能,线段树节点只需维护区间 $[l,r]$ 中的最小值 $\text{mn}$,以及最小值的长度总和 $s$。查询的时候,如果 tr[1].mn == 0,那么有标记的长度总和就是 n - tr[1].s;否则是 n

  AC 代码如下,时间复杂度为 $O(n + m \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5;

vector<int> l[N], r[N];
struct Node {
    int l, r, mn, s, add;
}tr[N * 4];

void build(int u, int l, int r) {
    tr[u] = {l, r, 0, r - l + 1, 0};
    if (l != r) {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
    }
}

void upd(int u, int c) {
    tr[u].mn += c;
    tr[u].add += c;
}

void pushdown(int u) {
    if (!tr[u].add) return;
    upd(u << 1, tr[u].add);
    upd(u << 1 | 1, tr[u].add);
    tr[u].add = 0;
}

void modify(int u, int l, int r, int c) {
    if (l > r) return;
    if (tr[u].l >= l && tr[u].r <= r) {
        upd(u, c);
    }
    else {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, c);
        if (r >= mid + 1) modify(u << 1 | 1, l, r, c);
        tr[u].mn = min(tr[u << 1].mn, tr[u << 1 | 1].mn);
        tr[u].s = 0;
        if (tr[u << 1].mn == tr[u].mn) tr[u].s += tr[u << 1].s;
        if (tr[u << 1 | 1].mn == tr[u].mn) tr[u].s += tr[u << 1 | 1].s;
    }
}

void solve() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        l[i].clear(), r[i].clear();
    }
    build(1, 1, n);
    while (m--) {
        int a, b;
        scanf("%d %d", &a, &b);
        l[a].push_back(b);
        r[b].push_back(a);
        modify(1, a, b - 1, 1);
    }
    int ret = n;
    for (int i = 1; i <= n; i++) {
        for (auto &x : l[i]) {
            int a = i, b = x;
            modify(1, a, b - 1, -1);
            modify(1, 1, a - 1, 1);
            modify(1, b, n, 1);
        }
        for (auto &x : r[i]) {
            int a = x, b = i;
            modify(1, 1, a - 1, -1);
            modify(1, b, n, -1);
            modify(1, a, b - 1, 1);
        }
        ret = min(ret, tr[1].mn ? n : n - tr[1].s);
    }
    printf("%d\n", ret);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round 962 (Div. 3) Editorial:https://codeforces.com/blog/entry/131528

标签:10,路径,house,Penacony,leq,roads,rightarrow
From: https://www.cnblogs.com/onlyblues/p/18327187

相关文章

  • 每日一题-CF1996G Penacony
    异常明显的思路,考场上却不会,连确定一条边不选都没想到#include<bits/stdc++.h>usingnamespacestd;#definepiipair<int,int>#definefifirst#definesesecond#definempmake_pair#definels(rt<<1)#definers(rt<<1|1)#definemid(l+r>>1)intt,n,m......