并查集,用并查集的好处是题目中要求找出最小的下标,并查集需要用一个特征来表示唯一的祖先
需要 fa数组表示各编号的祖先,一个set集合用来记录所有出现过的人的编号,然后就是一个够大的数组记录房产信息(这里其实可以完全不用数组,用一个map编号直接映射房产信息的结构体就完了,这更节省空间),用并查集写很方便的地方在于不用创建很大的数组(除了fa数组),还有就是只需要遍历所有编号就能得出所有结果了,遍历的顺序对结果没有任何影响,因为只要是一个家族里面的,其祖先就是唯一的(最小的那个下标)
代码
import java.util.*;
public class Main {
public static class UnionQuerySet {
static int[] arr = new int[10100];
public static int find(int i){
if(arr[i] == i){
return i;
}
else{
return find(arr[i]);
}
}
public static void union(int i, int j){
int f1 = find(i);
int f2 = find(j);
if(f1 > f2){
arr[f1] = f2;
}
else{
arr[f2] = f1;
}
}
public static void init()
{
for(int i = 0; i < arr.length; i++){
arr[i] = i;
}
}
public static void main(String[] args) {
init();
for(int i = 0; i < arr.length - 3; i+=2){
union(i, i+2);
}
for(int i = 1; i < arr.length-2; i+=2){
union(i, i+2);
}
Map<Integer, List<Integer>> map = new HashMap<>();
for(int i = 0; i < arr.length; i++){
int root = find(i);
if(map.containsKey(root)){
List<Integer> lst = map.get(root);
lst.add(i);
}
else{
List<Integer> lst = new ArrayList<>();
lst.add(i);
map.put(root,lst);
}
}
for(Map.Entry<Integer,List<Integer>> entry : map.entrySet()){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
public static class FamilyInfo implements Comparable<FamilyInfo>{
// 家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积
private int mid;
private int people_num;
private int house_num_per_person;
private double avg_area;
public FamilyInfo(int mid, int people_num, int house_num_per_person, double avg_area) {
this.mid = mid;
this.people_num = people_num;
this.house_num_per_person = house_num_per_person;
this.avg_area = avg_area;
}
public int getMid() {
return mid;
}
public void setMid(int mid) {
this.mid = mid;
}
public int getPeople_num() {
return people_num;
}
public void setPeople_num(int people_num) {
this.people_num = people_num;
}
public int getHouse_num_per_person() {
return house_num_per_person;
}
public void setHouse_num_per_person(int house_num_per_person) {
this.house_num_per_person = house_num_per_person;
}
public double getAvg_area() {
return avg_area;
}
public void setAvg_area(double avg_area) {
this.avg_area = avg_area;
}
@Override
public int compareTo(FamilyInfo o) {
if(this.avg_area/this.people_num > o.avg_area/o.getPeople_num()){
return -1;
}
else if(this.avg_area/this.people_num < o.avg_area/o.getPeople_num()){
return 1;
}
else {
return this.mid - o.mid;
}
}
}
public static class HouseInfo {
private int house_num;
private int total_area;
public HouseInfo(int house_num, int total_area) {
this.house_num = house_num;
this.total_area = total_area;
}
public int getHouse_num() {
return house_num;
}
public void setHouse_num(int house_num) {
this.house_num = house_num;
}
public int getTotal_area() {
return total_area;
}
public void setTotal_area(int total_area) {
this.total_area = total_area;
}
}
public static void main(String[] args) {
UnionQuerySet.init();
// 10
//2333 -1 3721 3 6661 6662 6663 1 100
Set<Integer> personSet = new HashSet<>();
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
scanner.nextLine();
Map<Integer, HouseInfo> map = new HashMap<>();
for (int i = 0; i < num; i++) {
String line = scanner.nextLine();
String[] info = line.split(" ");
int person_id = Integer.parseInt(info[0]);
int father_id = Integer.parseInt(info[1]);
int mother_id = Integer.parseInt(info[2]);
int child_num = Integer.parseInt(info[3]);
int house_num = Integer.parseInt(info[info.length - 2]);
int total_area = Integer.parseInt(info[info.length - 1]);
HouseInfo houseInfo = new HouseInfo(house_num, total_area);
personSet.add(person_id);
if (father_id != -1) {
UnionQuerySet.union(person_id, father_id);
personSet.add(father_id);
}
if (mother_id != -1) {
UnionQuerySet.union(person_id, mother_id);
personSet.add(mother_id);
}
for(int j = 0; j < child_num; j++){
int child_id = Integer.parseInt(info[4+j]);
UnionQuerySet.union(person_id, child_id);
personSet.add(child_id);
}
map.put(person_id, houseInfo);
}
Map<Integer, FamilyInfo> map2 = new HashMap<>();
for(Integer pId : personSet){
int root = UnionQuerySet.find(pId);
if(map2.containsKey(root)){
FamilyInfo familyInfo = map2.get(root);
int house_num_per_person = 0;
double avg_area = 0;
if(map.containsKey(pId)){
house_num_per_person = map.get(pId).getHouse_num();
avg_area = map.get(pId).getTotal_area();
}
familyInfo.setPeople_num(familyInfo.getPeople_num() + 1);
familyInfo.setHouse_num_per_person(familyInfo.getHouse_num_per_person()+house_num_per_person);
familyInfo.setAvg_area(familyInfo.getAvg_area()+avg_area);
// map2.put(root, familyInfo);
}
else{
int house_num_per_person = 0;
double avg_area = 0;
if(map.containsKey(pId)){
house_num_per_person = map.get(pId).getHouse_num();
avg_area = map.get(pId).getTotal_area();
}
FamilyInfo familyInfo = new FamilyInfo(root, 1, house_num_per_person, avg_area);
map2.put(root, familyInfo);
}
}
List<FamilyInfo> familyInfoList = new ArrayList<>();
for(Map.Entry<Integer, FamilyInfo> entry : map2.entrySet()){
familyInfoList.add(entry.getValue());
}
Collections.sort(familyInfoList);
System.out.println(familyInfoList.size());
for(FamilyInfo familyInfo : familyInfoList){
System.out.print(String.format("%04d",familyInfo.getMid()));
System.out.print(" "+familyInfo.getPeople_num()+" ");
System.out.printf("%.3f",familyInfo.getHouse_num_per_person()*1.0/familyInfo.getPeople_num());
System.out.print(" ");
System.out.printf("%.3f", familyInfo.getAvg_area()/familyInfo.getPeople_num());
System.out.println();
}
}
}