传送门: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 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 协议。转载请注明出处!