Welcome Party ZOJ - 4109 (思维+并查集)

题目链接:

Welcome Party

 ZOJ - 4109 

题目大意:给你T组测试样例,然后n个人,m个关系,每一个关系包括两个人,这两个人为好朋友,然后问你怎么安排顺序,使得整个队伍的友情损失度最小(当一个人放置时,如果他的前面中没有他的朋友,那么整个队伍的朋友损失度就会加1)

具体思路:首先用并查集求出每一个联通块,然后用一个超级汇点连向这些连通块的根,然后优先队列+bfs求出字典序最小的正解就可以了。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define inf 0x3f3f3f3f
 4 # define ll long long
 5 const int maxn = 2e6+100;
 6 int father[maxn];
 7 vector<int>Edge[maxn];
 8 vector<int>sto;
 9 int vis[maxn];
10 int Find(int t)
11 {
12     return t==father[t]?t:father[t]=Find(father[t]);
13 }
14 void mege(int st,int ed)
15 {
16     int t1=Find(st);
17     int t2=Find(ed);
18     if(t1==t2)return ;
19     if(t1>t2)swap(t1,t2);
20     father[t2]=t1;
21 }
22 void bfs(int root)
23 {
24     priority_queue<int,vector<int>,greater<int> >q;
25     while(!q.empty())q.pop();
26     q.push(root);
27     vis[root]=1;
28     while(!q.empty())
29     {
30         int top=q.top();
31         q.pop();
32     //    if(top!=0)
33         sto.push_back(top);
34         for(int i=0; i<Edge[top].size(); i++)
35         {
36             int to=Edge[top][i];
37             if(vis[to])
38                 continue;
39             vis[to]=1;
40             q.push(to);
41         }
42     }
43 }
44 int main()
45 {
46     int T;
47     scanf("%d",&T);
48     while(T--)
49     {
50         int n,m,st,ed;
51         scanf("%d %d",&n,&m);
52         sto.clear();
53         for(int i=0; i<=n; i++)//注意从0开始清空
54         {
55             father[i]=i;
56             Edge[i].clear();
57             vis[i]=0;
58         }
59         for(int i=1; i<=m; i++)
60         {
61             scanf("%d %d",&st,&ed);
62             Edge[st].push_back(ed);
63             Edge[ed].push_back(st);
64             mege(st,ed);
65         }
66         int ans=0;
67         for(int i=1; i<=n; i++)
68         {
69             if(Find(i)!=i)
70                 continue;
71             Edge[0].push_back(i);
72             ans++;
73         }
74         bfs(0);
75         printf("%d\n",ans);
76         for(int i=1; i<sto.size(); i++)
77         {
78             if(i==1)
79                 printf("%d",sto[i]);
80             else
81                 printf(" %d",sto[i]);
82         }
83         printf("\n");
84     }
85     return 0;
86 }

 

转载于:https://www.cnblogs.com/letlifestop/p/10804321.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值