0
点赞
收藏
分享

微信扫一扫

ZOJ Problem 4109 Welcome Party (并查集+优先队列输出字典序)

AbrahamW 2023-02-07 阅读 51


Welcome Party

Time Limit: 2 Seconds      Memory Limit: 131072 KB

The 44th World Finals of the International Collegiate Programming Contest (ICPC 2020) will be held in Moscow, Russia. To celebrate this annual event for the best competitive programmers around the world, it is decided to host a welcome party for all  participants of the World Finals, numbered from  to  for convenience.

The party will be held in a large hall. For security reasons, all participants must present their badge to the staff and pass a security check in order to be admitted into the hall. Due to the lack of equipment to perform the security check, it is decided to open only one entrance to the hall, and therefore only one person can enter the hall at a time.

Some participants are friends with each other. There are  pairs of mutual friendship relations. Needless to say, parties are more fun with friends. When a participant enters the hall, if he or she finds that none of his or her friends is in the hall, then that participant will be unhappy, even if his or her friends will be in the hall later. So, one big problem for the organizer is the order according to which participants enter the hall, as this will determine the number of unhappy participants. You are asked to find an order that minimizes the number of unhappy participants. Because participants with smaller numbers are more important (for example the ICPC director may get the number 1), if there are multiple such orders, you need to find the lexicographically smallest one, so that important participants enter the hall first.

Please note that if participant  and  are friends, and if participant  and  are friends, it's NOT necessary that participant  and  are friends.

Input

There are multiple test cases. The first line of the input contains a positive integer , indicating the number of cases. For each test case:

The first line contains two integers  and  (), the number of participants and the number of friendship relations.

The following  lines each contains two integers  and  (), indicating that the -th and the -th participant are friends. Each friendship pair is only described once in the input.

It is guaranteed that neither the sum of  nor the sum of  of all cases will exceed .

Output

For each case, print a single integer on the first line, indicating the minimum number of unhappy participants. On the second line, print a permutation of  to  separated by a space, indicating the lexicographically smallest ordering of participants entering the hall that achieves this minimum number.

Consider two orderings  and , we say  is lexicographically smaller than , if there exists an integer  (), such that  holds for all , and .

Please, DO NOT output extra spaces at the end of each line, or your solution may be considered incorrect!

Sample Input


2 4 3 1 2 1 3 1 4 4 2 1 2 3 4


Sample Output


1 1 2 3 4 2 1 2 3 4


Author: YAN, Jiangzhe
Source: The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple

​​Submit​​​    ​​Status​​

题意:

n个人,m给关系,n个进入会场,如果会场没有认识的人,则这个人会不高兴,注意,关系之间不可传递,朋友的朋友不一定是朋友。问不高兴的人数最少,并且输出字典序最小的入场方案。

分析:

不高兴的人数最少肯定为连通块的个数一个并查集就ok,关键是字典序输出。

对于整体来说,下标标号越小越好,对于每一个连通块我们选下标最小的人作为父亲节点(即为不高兴的人),让其作为整个连通块最先输出的点。首先,对其不高兴的人,选出最小编号的人进会场,然后让其的周围的朋友加入优先队列
 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1000005;
int fa[maxn],flag[maxn];
int n,m;
const int N=1000005;
//结构体数组edge存边,edge[i]表示第i条边,
//head[i]存以i为起点的第一条边(在edge中的下标)
int head[N],tot;
struct node
{
int next; //下一条边的存储下标
int to; //这条边的终点
int w; //权值
} edge[N*4];
void Add(int u, int v, int w) //起点u, 终点v, 权值w
///tot为边的计数,从0开始计,每次新加的边作为第一条边,最后倒序遍历
{
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
priority_queue<int,vector<int>,greater<int> >pq;
int cnt=1;
void bfs()
{
cnt=0;
while(!pq.empty())
{
int u=pq.top();
pq.pop();
cnt++;
if(cnt==n)
printf("%d\n",u);
else
printf("%d ",u);

for(int i=head[u]; i!=-1; i=edge[i].next) //遍历以u为起点的所有边,与输入顺序相反
{
int v=edge[i].to;
if(flag[v]==0)
{
pq.push(v);
flag[v]=1;
}
}
}


}
int findd(int x)
{
if(x==fa[x])
return x;
return fa[x]=findd(fa[x]);
}
void mergee(int x,int y)
{
int x1=findd(x);
int y1=findd(y);
if(x1!=y1)
{
if(y1>x1)
fa[y1]=x1;
else
fa[x1]=y1;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
while(!pq.empty())
pq.pop();
scanf("%d%d",&n,&m);
//init();
tot=0;
for(int i=1; i<=n; i++)
{
fa[i]=i;
flag[i]=0;
head[i]=-1;
}
int u,v;

for(int i=1; i<=m; ++i)
{
scanf("%d%d",&u,&v);

mergee(u,v);
Add(u,v,0);
Add(v,u,0);
}
int ans=0;
for(int i=1; i<=n; i++)
{
if(findd(i)==i)
{
ans++;
pq.push(i);
flag[i]=1;
}
}
printf("%d\n",ans);


bfs();

}
return 0;
}

举报

相关推荐

0 条评论