传送门: https://codeforces.ml/contest/1465/problem/C
题意
给
n
∗
n
的
棋
盘
,
有
m
个
棋
子
,
每
个
棋
子
都
有
一
个
坐
标
(
x
,
y
)
。
给n*n的棋盘,有m个棋子,每个棋子都有一个坐标(x,y)。
给n∗n的棋盘,有m个棋子,每个棋子都有一个坐标(x,y)。
问
怎
么
移
动
使
每
个
棋
子
都
移
动
到
棋
盘
的
主
对
角
线
上
,
求
最
小
移
动
数
。
问怎么移动使每个棋子都移动到棋盘的主对角线上,求最小移动数。
问怎么移动使每个棋子都移动到棋盘的主对角线上,求最小移动数。
注 意 : 每 移 动 依 次 , 不 能 使 两 个 棋 子 在 同 一 列 或 同 一 行 。 注意:每移动依次,不能使两个棋子在同一列或同一行。 注意:每移动依次,不能使两个棋子在同一列或同一行。
思路
有 两 种 情 况 : 有两种情况: 有两种情况:
- x等于y,不需要移动,理想情况
- x不等于y,我们可以一步将棋子移到(x,x)或(y,y),但是在那一列或那一行中已经有棋子了,所以将那一颗棋子移走,但是还有下一颗棋子也会占掉它的位置。
如
果
没
有
出
现
环
的
情
况
,
而
是
一
条
链
,
那
直
接
按
照
上
面
操
作
。
如果没有出现环的情况,而是一条链,那直接按照上面操作。
如果没有出现环的情况,而是一条链,那直接按照上面操作。
如
果
出
现
环
的
情
况
,
先
把
一
个
棋
子
从
环
上
移
动
变
成
链
,
只
不
过
操
作
数
+
1
而
已
。
如果出现环的情况,先把一个棋子从环上移动变成链,只不过操作数+1而已。
如果出现环的情况,先把一个棋子从环上移动变成链,只不过操作数+1而已。
处 理 有 没 有 环 只 要 用 并 查 集 判 断 即 可 。 处理有没有环只要用并查集判断即可。 处理有没有环只要用并查集判断即可。
Code
#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();
}