Codeforces Round

传送门:https://codeforces.ml/contest/1465/problem/C

题意

给n*n的棋盘,有m个棋子,每个棋子都有一个坐标(x,y)。 问怎么移动使每个棋子都移动到棋盘的主对角线上,求最小移动数。

注意:每移动依次,不能使两个棋子在同一列或同一行。

思路

有两种情况:

  • x等于y,不需要移动,理想情况
  • x不等于y,我们可以一步将棋子移到(x,x)或(y,y),但是在那一列或那一行中已经有棋子了,所以将那一颗棋子移走,但是还有下一颗棋子也会占掉它的位置。

如果没有出现环的情况,而是一条链,那直接按照上面操作。 如果出现环的情况,先把一个棋子从环上移动变成链,只不过操作数+1而已。

处理有没有环只要用并查集判断即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

##include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

##define lc u << 1
##define rc u << 1 1
##define mid (t[u].l + t[u].r) / 2
##define INF 0x3f3f3f3f
##define lowbit(x) x & (-x)
##define mem(a, b) memset(a , b , sizeof(a))
##define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const ll mod = 1e9 + 7;
// const double eps = 1e-6;
// const double PI = acos(-1);
// const double R = 0.57721566490153286060651209;

const int N = 1e5 + 10;
int fa[N];

int find(int x) {
return fa[x] == x? x : fa[x] = find(fa[x]);
}

void solve() {
int _; cin >> _;
while(_--) {
int n, m;
cin >> n >> m;
for(int i = 1;i <= n; i++) fa[i] = i;
int cnt = 0;
for (int i = 1; i <= m; i++) {
int x, y;
cin >> x >> y;
if (x == y) continue;
else {
cnt++;
int u = find(x);
int v = find(y);
if (u == v) cnt++;
fa[u] = v;
}
}
cout << cnt << endl;
}
}

signed main() {
solve();
}

本文作者:jujimeizuo
本文地址https://blog.jujimeizuo.cn/2020/12/21/codeforces-round-692-div2-c/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!