ZOJ-4109 Welcome Party(并查集+BFS+优先队列)

题目链接

题意:
有n个人要参加聚会,1~n分别表示他们的序列,m行表示他们之间的关系,这n个人一次进场,若进场后发现没有自己的朋友,这个人就会不开心。现在要求排他们的入场顺序,使得不开心的人数最少,同时,进场人的字典序最小。
思路:
由于他们的关系可以用联通图表示,则每一个联通块必然至少会有一个人不开心,所以用并查集判断联通块个数。同时再用0号表示超级源点,依次将他们的朋友放进优先队列中,出队顺序就是入场顺序。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1000050;
int  pre[MAXN],cnt;     //保存节点的直接父节点
vector<int>ve[MAXN];
int ans[MAXN],vis[MAXN];
//查找x的根节点
int Find(int x){
    if(pre[x]!=x)
        pre[x]=Find(pre[x]);//路径压缩,本结点更新为根结点的子结点
    return pre[x];
}
//连接两个连通块
void join(int x,int y) {
    int fx=Find(x),fy=Find(y);
    if(fx>fy) pre[fx]=fy;
    else pre[fy]=fx;
}

void BFS(int x)
{
    priority_queue<int,vector<int>,greater<int> > q;
    q.push(x);
    while(!q.empty()){
        int now = q.top();q.pop();
        if(!vis[now]){
            vis[now]=1;
            ans[cnt++]=now;	//出队顺序是入场顺序
            for(int i=0;i<ve[now].size();i++){
                if(!vis[ve[now][i]]){
                    q.push(ve[now][i]);
                }
            }
        }
    }
}

int main() {
    int T;
    cin>>T;
    while(T--){
        int N,M,a,b,i,j,ans1=0;
        scanf("%d%d",&N,&M);
        //初始化pre数组
        for(i=0;i<=N;i++){
            pre[i]=i;//根据连通情况,构建pre数组
            vis[i]=0;
            ve[i].clear();
        }
        for(i=1;i<=M;i++) {
            scanf("%d%d",&a,&b);
            ve[a].push_back(b);
            ve[b].push_back(a);
            join(a,b);
        }
        for(i=1;i<=N;i++){
            if(pre[i]==i){
                ans1++; //计算连通子图的个数ans
                ve[0].push_back(i);
            }
        }
        cnt=0;
        BFS(0);
        cout<<ans1<<endl;
        for(int i=1;i<cnt;i++){
            if(i==1)    printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值