亲宝软件园·资讯

展开

ZOJ 4109 Welcome Party

俩小圈 人气:1

题目链接:(https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370504)(https://vjudge.net/problem/ZOJ-4109)

题面复制不过来。

题意:n个人,编号为1~n,m个朋友关系(a和b是朋友,a和c是朋友不代表b和c是朋友),将n个人按照顺序排好,如果一个人前面没有他的朋友那么不满意度加一,让你给出一个排序使得不满意度最小化,有相同结果的排序输出字典序最小的那个。

有关系存在,考虑画图。画完图后发现不满意度的最小值即是图的连通分量的个数,因为每当选定一个连通分量的的人进入序列,与他连接的人就可以都顺着连接加入序列,从而不会增加不满意度。求连通分量个数可用并查集实现。

要求输出字典序最小的,想到了用优先队列实现的bfs,优先选择队列中编号最小的点。

因为用memset导致超时好几次,初始化时最好用多少初始化多少。

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <queue>
  6 typedef long long ll;
  7 using namespace std;
  8 
  9 const int N=1e6+5;
 10 
 11 struct cmp {
 12     bool operator()(int a,int b) {
 13         return a>b;
 14     } 
 15 };
 16 
 17 priority_queue <int,vector <int>,cmp> Q;
 18 
 19 int E[N<<1],fir[N],nex[N<<1],tot;
 20 int per[N];
 21 bool vis[N];
 22 bool book[N];
 23 int n,m,cnt;
 24 
 25 void init() {
 26     for(int i=1;i<=n;i++) {
 27         per[i]=i;fir[i]=-1;vis[i]=false;book[i]=false;
 28     }
 29     cnt=tot=0;
 30 }
 31 
 32 void connect(int from,int to) {
 33     E[tot]=to;
 34     nex[tot]=fir[from];
 35     fir[from]=tot++;
 36     E[tot]=from;
 37     nex[tot]=fir[to];
 38     fir[to]=tot++;
 39 }
 40 
 41 int root(int x) {
 42     int tempa,tempb;
 43     tempa=x;
 44     while(x!=per[x]) x=per[x];
 45     while(per[tempa]!=x) {
 46         tempb=per[tempa];
 47         per[tempa]=x;
 48         tempa=tempb;
 49     }
 50     return x;
 51 }
 52 
 53 void merge(int x,int y) {
 54     int t1=root(x);
 55     int t2=root(y);
 56     if(t1!=t2) {
 57         per[t1]=t2;cnt++;
 58     }
 59 }
 60 
 61 void solve() {
 62     int cnt=0;
 63     while(!Q.empty()) {
 64         int q=Q.top();Q.pop();
 65         if(vis[q]) continue;
 66         vis[q]=true;
 67         cnt++;
 68         printf("%d",q);
 69         if(cnt!=n) printf(" ");
 70         for(int i=fir[q];i!=-1;i=nex[i]) {
 71             int to=E[i];
 72             if(!vis[to]) Q.push(to);
 73         }
 74     }
 75     printf("\n");
 76 }
 77 
 78 int main() {
 79     int t;
 80     scanf("%d",&t);
 81     while(t--) {
 82         scanf("%d%d",&n,&m);
 83         init();
 84         for(int i=1;i<=m;i++) {
 85             int x,y;
 86             scanf("%d%d",&x,&y);
 87             connect(x,y);
 88             merge(x,y);
 89         }
 90         printf("%d\n",n-cnt);
 91         for(int i=1;i<=n;i++) {
 92             if(!book[root(i)]) {
 93                 book[root(i)]=true;
 94                 Q.push(i);
 95             } 
 96         }
 97         solve();
 98     }
 99     return 0;
100 }

 

加载全部内容

相关教程
猜你喜欢
用户评论