ZOJ 4109 Welcome Party

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

題面複製不過來。spa

題意:n我的,編號爲1~n,m個朋友關係(a和b是朋友,a和c是朋友不表明b和c是朋友),將n我的按照順序排好,若是一我的前面沒有他的朋友那麼不滿意度加一,讓你給出一個排序使得不滿意度最小化,有相同結果的排序輸出字典序最小的那個。.net

有關係存在,考慮畫圖。畫完圖後發現不滿意度的最小值便是圖的連通份量的個數,由於每當選定一個連通份量的的人進入序列,與他鏈接的人就能夠都順着鏈接加入序列,從而不會增長不滿意度。求連通份量個數可用並查集實現。code

要求輸出字典序最小的,想到了用優先隊列實現的bfs,優先選擇隊列中編號最小的點。blog

由於用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 }
相關文章
相關標籤/搜索