地址: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; } }