题目链接:https://codeforc.es/contest/1465/problem/C
You are given a n×n chessboard. Rows and columns of the board are numbered from 1 to n. Cell (x,y) lies on the intersection of column number x and row number y.
Rook is a chess piece, that can in one turn move any number of cells vertically or horizontally. There are m rooks (m<n) placed on the chessboard in such a way that no pair of rooks attack each other. I.e. there are no pair of rooks that share a row or a column.
In one turn you can move one of the rooks any number of cells vertically or horizontally. Additionally, it shouldn’t be attacked by any other rook after movement. What is the minimum number of moves required to place all the rooks on the main diagonal?
The main diagonal of the chessboard is all the cells (i,i), where 1≤i≤n.
Input
The first line contains the number of test cases t (1≤t≤103). Description of the t test cases follows.
The first line of each test case contains two integers n and m — size of the chessboard and the number of rooks (2≤n≤105, 1≤m<n). Each of the next m lines contains two integers xi and yi — positions of rooks, i-th rook is placed in the cell (xi,yi) (1≤xi,yi≤n). It’s guaranteed that no two rooks attack each other in the initial placement.
The sum of n over all test cases does not exceed 105.
Output
For each of t test cases print a single integer — the minimum number of moves required to place all the rooks on the main diagonal.
It can be proved that this is always possible.
Example
input
4
3 1
2 3
3 2
2 1
1 2
5 3
2 3
3 1
1 2
5 4
4 5
5 1
2 2
3 3
output
1
3
4
2
题意
n * n 的位置, m 个点,每个点不能共行或共面,可以水平或垂直走,求让点在对角线上的移动的最小步数。
分析
每一列独立考虑,一个坐标为 (x, y) 的 s 点要去到他那一列的纵坐标为 y 的位置,他至少移动一步。
如果此时 y 行上已经有点 z,那么我们就看这个点能否一步移动到目标点,如果能,那么这两个点只需要两部即可都到目标点。
如果 z 点的目标点有阻碍(如阻碍即为 s 点)那么这两点至少三步……
代码
#include<bits/stdc++.h>
using namespace std;const int N = 1e5+7;
int row[N],vis[N];
struct node{
int x,y;
}a[N];
int ans;void dfs(int p)
{
vis[p] = 1;if(a[p].x == a[p].y) return;int to = row[a[p].y];if(to == 0){
ans++;vis[p] = -1;//-1标记为最终可以一步到达 return;}if(vis[to] == 0){
ans++;dfs(to);if(vis[to] == -1) vis[p] = -1;}else{
if(vis[to] == -1) ans++, vis[p] = -1;else ans += 2;}
}void solve()
{
int n,m;ans = 0;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) row[i] = 0, vis[i] = 0;for(int i=1;i<=m;i++){
scanf("%d%d",&a[i].x,&a[i].y);row[a[i].x] = i;}for(int i=1;i<=m;i++)if(vis[i] == 0) dfs(i);printf("%d\n",ans);
}int main()
{
int T;scanf("%d",&T);while(T--){
solve();}return 0;
}