题目链接:
http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=6000
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
int n,m;
vector<int> t[N];//邻接表
int pre[N];//pre表示每个点的前点
priority_queue<int,vector<int>,greater<int> > pq;
int find(int x)
{
return pre[x]==x?x:pre[x]=find(pre[x]);
}
void merge(int a,int b)
{
int t1,t2;
t1=find(a);
t2=find(b);
if(t1!=t2)
{
if(t1<t2)
pre[t2]=t1;
else
pre[t1]=t2;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int aa,b;
int vis[n+1];
for(int i=1;i<=n;i++)
{
pre[i]=i;
t[i].clear();
vis[i]=0;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&aa,&b);
t[aa].push_back(b);//邻接表思想
t[b].push_back(aa);
merge(aa,b);
}
int block=0;
for(int i=1;i<=n;i++)//先把各个连通块的老小,在这里为连通块中最小的号进优先队列
{
if(pre[i]==i)
{
pq.push(i);
vis[i]=1;
block++;
}
}
int a[n];
memset(a,0,sizeof(a));
int d=0;
//用一个数组a存出队序列
//pq.push(0);
while(!pq.empty())
{
int x=pq.top();pq.pop();
a[d++]=x;
for(int j=0;j<t[x].size();j++)
{
int b=t[x][j];
if(!vis[b])
{
pq.push(b);
vis[b]=1;
}
}
}
printf("%d\n",block);
for(int i=0;i<n;i++)
{
if(i==0)
printf("%d",a[i]);
else
printf(" %d",a[i]);
}
printf("\n");
}
return 0;
}
主要思想:并查集求连通块,用优先队列存放每个连通块的老小,遍历邻接表,依次判断入队出队即可;