这题真打脸,比赛的时候愣是没写出来(因为当天写了蓝桥杯上的历届试题--剪格子,这题数据很水,被搞晕了),现在回过头来看看,很简单,就是单纯找联通块,。
AC代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000+10;
int g[maxn][maxn];
int vis[maxn];
int n,m;
void dfs(int i){
for(int j=1;j<=n;j++){
if(g[i][j] && !vis[j]){
vis[j]=1;
dfs(j);
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
memset(g,0,sizeof(g));
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
g[a][b]=g[b][a]= 1;
}
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1;i<=n;i++){
if(!vis[i])
{
vis[i]=1;
dfs(i);
cnt++;
}
}
printf("%d\n",cnt);
}
return 0;
}
并查集:
AC代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000;
int pre[maxn];
int N,M;
int tol;
int find(int x){
return pre[x]==x?x:find(pre[x]);
}
void Union(int a,int b){
int fx=find(a),fy=find(b);
if(fx!=fy){
tol++;
pre[fx]=fy;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&M);
tol=0;
for(int i=1;i<=N;i++)
pre[i]=i;
for(int i=0;i<M;i++){
int a,b;
scanf("%d%d",&a,&b);
Union(a,b);
}
printf("%d\n",N-tol);
}
return 0;
}