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;
}