C. Peaceful Rooks

C. Peaceful Rooks
图论的一道题目,这道题可以用并查集来维护。
每当题目给出一个坐标,将这个坐标分解成两个点,然后将这两个点串起来,后面的点同理,不过还要判断是否能够和前面的点串起来,如果能串起来就串。最后需要判断在某一个点时是否能够串成一个环。如果串不成一个环,那么这些穿起来的就是一条路径,而路径就不需要再对其中的某一个点进行让步操作了,直接移动就好了。
如果能够串成一个环,那么就代表点之间有冲突,解决办法就是移动其中的一个点(首尾都行),那么对于这个环内的点来说,移动的答案就是点的个数加一,而对于一条路径来说,答案就是路径中所有点的个数。
对于环可以用并查集来维护,当发现某两个点能够连接到一个公共祖先时,那么就代表形成了一个环。

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 200050;
struct Node{
    int x, y;
}node[N];
int fa[N];

int find(int x){
    if(x == fa[x])
        return x;
    else
        return fa[x] = find(fa[x]);
}
void solve(){
    for(int i = 1; i <= 200010; i ++)
        fa[i] = i;
    int n, m, cnt = 0, ver = 1;
    cin >> n >> m;
    for(int i = 1; i <= m; i ++){
        int x, y;
        cin >> x >> y;
        if(x == y)
            continue;
        else
            node[ver].x = x, node[ver].y = y;
        int fx = find(node[ver].x);
        int fy = find(node[ver].y);
        if(fx != fy)
            fa[fx] = fy;
        else
            cnt ++;
        ver ++;
    }
    cout << cnt + ver - 1 << endl;
    return;
}
int main(){
    int t;
    cin >> t;
    while(t --){
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值