Codeforces Round #692 Div2 C題 並查集找環
阿新 • • 發佈:2020-12-22
技術標籤:並查集
Codeforces Round #692 Div2 C題 並查集找環
傳送門: 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();
}