Codeforces Round #692 Div2 C.Peaceful Rooks(並查集判環)
阿新 • • 發佈:2020-12-22
地址:http://codeforces.com/contest/1465/problem/C
題意:
給出n*n的棋盤,初始m個棋子,初始位置:一行只有一個棋子,一列只有一個棋子。
移動:水平或垂直移到任意一個位置。
將所有棋子移到主對角線上,需要最少的步數。每次移動的落點必須要符合:一行只有一個棋子,一列只有一個棋子。
解析:
x==y,無需操作。
x!=y,直接移的話,每個點只需要一次移動就可以。但是由於條件限制,那麼會存在一個點,需要移動兩次,才能騰出位置來讓其他棋子移動。
根據觀察,對每個x->y建邊,有幾個環,就有幾個點需要移動兩次,其他的x!=y的移動一次就可以了。
#include<iostream> #include<cstring> #include<map> #include<queue> #include<algorithm> #include<stack> #include<queue> #include<cstdio> #include<cmath> #include<string.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int>P;const int maxn=1e5+10; const int inf=99999999; int pr[maxn]; int find(int x) { if(x!=pr[x]) return pr[x]=find(pr[x]); return x; } int main() { int t; cin>>t; while(t--) { int n , m; cin>>n>>m; for(int i=1;i<=n;i++) pr[i]=i; int x,y; int cnt = 0 ,cnt2=0; for(int i=1;i<=m;i++) { cin>>x>>y; if(x==y) { cnt2++; continue; } int f1=find(x),f2=find(y); if(f1!=f2) { pr[f1]=f2; } else cnt++; } // cout<<cnt<<"--"<<endl; cout<<cnt+m-cnt2<<endl; } }