1. 程式人生 > 其它 >Codeforces Round #692 Div2 C題 並查集找環

Codeforces Round #692 Div2 C題 並查集找環

技術標籤:並查集

Codeforces Round #692 Div2 C題 並查集找環


傳送門: https://codeforces.ml/contest/1465/problem/C

題意

給 n ∗ n 的 棋 盤 , 有 m 個 棋 子 , 每 個 棋 子 都 有 一 個 坐 標 ( x , y ) 。 給n*n的棋盤,有m個棋子,每個棋子都有一個座標(x,y)。 nnm(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(); }