ZOJ - 4109 - Welcome Party (并查集 + BFS + 优先队列)
Posted jiaaaake
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ - 4109 - Welcome Party (并查集 + BFS + 优先队列)相关的知识,希望对你有一定的参考价值。
题目大意:n个人,m种关系 (a和b是朋友),可以看作 n个点,m条边, 用图论的知识解题
问在使最少人不开心的情况下,输出进房间字典序排序最小的顺序。(如果在小A进房间之前房间内没有他的朋友,他就不开心)
使用并查集分块,每个并查集的根节点和独立点(无朋友)的总个数就是输出的不开心的人数。
使用BFS和优先队列遍历存入的图,保证字典序最小。将路径存入答案数组。
代码:
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6+5; int s[maxn]; int vis[maxn]; vector<int> Edge[maxn]; //二维! vector<int> sto; //答案 int Find(int t) return t==s[t]?t:s[t]=Find(s[t]); void Merge(int st,int ed) int t1=Find(st); int t2=Find(ed); if(t1==t2) return; if(t1>t2)swap(t1,t2); s[t2]=t1; void bfs(int root) priority_queue<int,vector<int>,greater<int> > Q; while(!Q.empty()) Q.pop(); Q.push(root); vis[root] = 1; while(!Q.empty()) int t = Q.top(); Q.pop(); sto.push_back(t); // cout << " size = " << sto.size() << endl; for(int i = 0; i < Edge[t].size(); i++) int temp = Edge[t][i]; if(vis[temp]) continue; vis[temp] = 1; Q.push(temp); int main() int T, n, m; cin >> T; while(T--) int ans = 0; cin >> n >> m; sto.clear(); //清空答案数组!! for(int i = 0; i <= n; i++) //从0开始,把所有根节点和无朋友的点存在Edge[0]里面 s[i] = i; //并查集数组 Edge[i].clear(); //存边(两点 vis[i] = 0; //标记数组 for(int i = 1; i <= m; i++) int x, y; cin >> x >> y; Edge[x].push_back(y); //关系是相互的 所以在Merge时需要判断大小 Edge[y].push_back(x); Merge(x, y); for(int i = 1; i <= n; i++) if(s[i] == i) //所有的根节点 和 不存在边的点(无朋友的) ans ++; Edge[0].push_back(i); bfs(0); printf("%d\n",ans); int len = sto.size(); for(int i = 1; i < len-1; i++) cout << sto[i] << " "; cout << sto[len-1] << endl; return 0;
以上是关于ZOJ - 4109 - Welcome Party (并查集 + BFS + 优先队列)的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ - 4109 - Welcome Party (并查集 + BFS + 优先队列)