https://codeforces.com/contest/1464/problem/A
一开始看错题了以为是走的长度总和,然后发现看错了以后心浮气躁不会做了
实际上就是个模型转化,首先本身在对角线上的肯定不用动,其次m<n,所以从事可以通过移动2步移动到对角线上,那么就是看有多少个移动2步和多少个移动1步
那么每个棋子移动一步就是要么移动到x,x,要么移动到y,y,而他们之间就可以抽象成一个图论问题,类似于2-sat
那么就可以用并查集维护,如果它的坐标x,x,y,y都被占领了,也就是并查集相同,他们就必须通过2步移动到一个没被站的对角线位置上
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,k,cnt,tot,cas,ans;
struct node
{
int x,y;
}a[maxl];
int f[maxl];
bool vis[maxl];
char s[maxl];
inline int find(int x)
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
f[i]=i;
ll ans=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
if(a[i].x==a[i].y)
continue;
ans++;
int xx=find(a[i].x),yy=find(a[i].y);
if(xx==yy)
ans++;
else
f[xx]=yy;
}
printf("%lld\n",ans);
}
inline void mainwork()
{
}
inline void print()
{
}
int main()
{
int t=1;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}