日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

PAT甲级1114 Family Property:[C++题解]结构体、并查集、测试点3、4、5有问题的进来!!

發布時間:2025/4/5 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PAT甲级1114 Family Property:[C++题解]结构体、并查集、测试点3、4、5有问题的进来!! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 題目分析
    • 題目鏈接

題目分析



來源:acwing

分析:

  • 先建邊。讀入每家的信息,在本人和父母(如果有的話),本人與子女(如果有的話)之間分別建邊。邊用結構體來存,邊記錄兩個端點。
  • 遍歷每條邊合并集合,分成一個一個家庭。這里的“遍歷每條邊”,指的是遍歷兩條邊的端點(戶主,或父母,或子女),利用find()函數合并,這里把id大的掛到id小的上面,這樣,根結點就是答案所求的戶主id。
  • 將每個家庭存入vector,排序輸出即可。為此,需要一個Family結構體,里面存戶主id,家庭人數c,家庭房子數量hc,家庭房子面積ha,并重載小于號進行排序。
  • 需要注意的點:

  • 用int表示id,不用string。起初想用string來表示id,發現較為麻煩。原因有二,一是用string之后,用并查集之后還需要一步從string到int 的映射,教麻煩。二是題目明確每個id都是4位數,并且各不相同,這是變相地給我們降級難度,提示我們使用int。
  • 家庭戶主的id是編號最小的。由于我們是用并查集做的,這就提示我們只維護一個最小的id即可,其他id在統計到各個家庭之后沒有什么用。在并查集中,合并的時候把較大的root接到較小的root上,這樣得到的root就是最小的root。
  • 前導0的輸出,萬能C語言!!!由于用int來存的id,如果像0004這樣嬸兒的,存的只是4,這就考驗我們的格式化輸出能力。使用printf("%04d",a);含義是以4位寬度輸出數a,不足4位的在前面補0!
  • 補充:printf("%4d",id)表示輸出寬度為4,且右對齊,不足的在前面補空格。當變量的實際寬度大于4時,輸出變量的所有數字.

    ac代碼

    #include<bits/stdc++.h> using namespace std; const int N = 10010; //邊的數量 int n; int p[N]; //并查集父親數組 int c[N];//c[i]表示i這家人的人數 count int hc[N];//房子數量 house count int ha[N]; //房子面積 house area bool st[N];// 戶主 和父母,子女分別建邊 struct Edge{int a, b; }e[N];// 一家人放在一個結構體中,排序使用 struct Family{int id ,c ,hc, ha;bool operator<(const Family & t)const{// ha /c , t.ha/t.cif( ha * t.c != c * t.ha) return ha * t.c > c* t.ha;return id < t.id;} };//并查集找根 int find(int x){if(p[x]!= x) p[x] = find(p[x]);return p[x]; }int main(){cin >>n;int m =0; //表示邊數//第一部分: 讀入所有輸入,并建邊for(int i = 0; i < n; i++){int id , father ,mother, k;cin >> id >> father >> mother >>k;//標記id出現過st[id] = true;if(father != -1) e[m++] = {id,father};if(mother != -1) e[m++] = {id,mother};for(int j = 0 ;j< k; j++){int son;cin >> son;e[m++] ={id,son};}cin >> hc[id] >> ha[id]; //房子數量,房子面積}//第二部分:得到每個家庭,并且戶主編號最小//并查集初始化for(int i = 0; i<= N; i++) p[i] = i,c[i] =1 ;//i這家人只有1個人//遍歷每條邊:合并集合:得到每個家庭。for(int i = 0 ; i<m ;i++){int a = e[i].a, b = e[i].b;st[a] = st[b] = true; //標記每個點出現過//一個集合的根結點int pa = find(a),pb = find(b);//合并集合,讓根結點大的集合掛到 根結點小的集合上!!//這樣根結點就是編號最小的那個!!!//題目要求:ID 是家庭成員中編號最小的成員編號if(pa != pb){if(pb > pa) swap(pa,pb); //讓pb成為較小的// 那么pb那個集合的值都要更新:加上pa集合的值//人數 , 房子數量,房子面積c[pb] += c[pa],hc[pb]+= hc[pa],ha[pb] += ha[pa];//pa集合掛到編號更小pb集合p[pa] = pb; }}// 第三部分:每個家庭的信息存起來,并輸出vector<Family> familys;//遍歷所有的點,如果之前出現過st[i] == true 并且是集合的根結點p[i] == i//代表i就是一家之主,將該家庭統計到vector中for(int i =0 ;i < N; i++){if(st[i] && p[i] == i)familys.push_back({i,c[i],hc[i],ha[i]});}//排序輸出sort(familys.begin(),familys.end());cout<< familys.size()<<endl;for( auto f :familys){printf("%04d %d %.3lf %.3lf\n",f.id, f.c,(double)f.hc/f.c,(double)f.ha/f.c);} }

    注意:測試點3、4、5包括0000這個人。第一遍忽略了這個人,導致三個測試點錯誤。

    題目鏈接

    PAT甲級1114 Family Property
    https://www.acwing.com/problem/content/1606/

    總結

    以上是生活随笔為你收集整理的PAT甲级1114 Family Property:[C++题解]结构体、并查集、测试点3、4、5有问题的进来!!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。