家庭房产

额。。一看到题目就感觉是用并差距来做,然后思路不是很清晰,还有点畏惧心理,怕麻烦心理。。这样不好不好。其实冷静下来,分析分析,还是蛮好做的
代码写的有点丑。。大概思想是这样的,先考虑有多少个家庭,以编号最小的为father。然后我们可以根据father来知道有几个家庭,然后家庭中的成员数是多少。房子数和面积先放在一个编号上,最后加起来就好了。ps,怎么根据并查集来看有多少个家庭呢?dis[i]==i?那这样的话不是有很多没有出现过的编号也加了进去么。所以我们怎么知道哪些编号我们是出现过的呢,然后我采用的是让dis先初始化为-1,然后出现过了的,我再赋值。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
struct node
{
  int bh,fz,rs,mj;
};
struct node1
{
  int bianhao;
  double renjun;
};
node dis[10005];
node1 fina[1005];
int findf(int k)
{
  if(dis[k].bh==k)
    return k;
  else
    return k=findf(dis[k].bh);
}
bool cmp(node1 a,node1 b)
{
  if(a.renjun!=b.renjun)
    return a.renjun>b.renjun;
  else
    return a.bianhao<b.bianhao;
}
int main()
{
  memset(dis,-1,sizeof(dis));
  int n;
  scanf("%d",&n);
  while(n--)
  {
    int vis[15],visf[15];
    memset(visf,0,sizeof(visf));
    int me,bb,mm,k,h=1,housenum,s;
    scanf("%d %d %d %d",&vis[0],&bb,&mm,&k);
    if(bb!=-1)
      vis[h++]=bb;
    if(mm!=-1)
      vis[h++]=mm;
    for(int i=1;i<=k;i++)
      scanf("%d",&vis[h++]);
    for(int i=0;i<h;i++)
      if(dis[vis[i]].bh==-1) {dis[vis[i]].bh=vis[i],dis[vis[i]].fz=0,dis[vis[i]].mj=0,dis[vis[i]].rs=1;}
    scanf("%d %d",&housenum,&s);
    for(int i=0;i<h;i++)
      visf[i]=findf(vis[i]);
    sort(visf,visf+h);
    int father=visf[0];
    dis[father].fz+=housenum;
    dis[father].mj+=s;
    for(int i=0;i<h;i++)
      dis[visf[i]].bh=father;
  }
  int ans=0;
  for(int i=0;i<10000;i++)
  {
    if(dis[i].bh!=-1)
    {
    int gg=findf(i);
    if(gg==i)
      {ans++;}
    else if(gg!=i)
    {
      dis[gg].fz+=dis[i].fz;
      dis[gg].mj+=dis[i].mj;
      dis[gg].rs+=dis[i].rs;
      dis[i].bh=gg;
    }
    }
  }
  printf("%d\n",ans);
  int gd=0;
  for(int i=0;i<10000;i++)
    if(dis[i].bh==i)
      {
        fina[gd].renjun=(double)dis[i].mj/dis[i].rs;
        fina[gd++].bianhao=i;}
  sort(fina,fina+gd,cmp);
  for(int i=0;i<gd;i++)
   printf("%04d %d %.3f %.3f\n",fina[i].bianhao,dis[fina[i].bianhao].rs,(double)dis[fina[i].bianhao].fz/dis[fina[i].bianhao].rs,(double)dis[fina[i].bianhao].mj/dis[fina[i].bianhao].rs);
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值