您的位置:首页 > 其它

天梯赛 L2 - 007 家庭房产 【并查集】

2018-03-26 19:16 232 查看
传送门

// 题意: 题意就不多说了. 直接开讲思路.

首先有一个家族关系, 那么肯定这个要用并查集维护, 然后家庭人数就是集合的size, 也比较好维护, 比较难做的点是维护集合中每一个点有房产的, 所以对于这种题, 就不要再用下标从1开始累加他们了, 直接用下标来代替他们的编号, 因为这个编号范围很小, 我们可以直接枚举所有在这个范围内的点, 这种题都是这种套路, 记好了! 然后就是标记出现过的点, 然后for一遍把所有集合都取出来即可. 并查集就是普通的并查集, 注意我这个写法有一个坑点就是编号可以为0, 我这个就会出bug, 所以要通过该集合的人数来判断…… 具体细节请看代码.

AC Code

const int maxn = 1e4+5;
int fa[maxn], r[maxn];
void init() {
for (int i = 0 ; i <= maxn-4 ; i ++) {
fa[i] = i;
r[i] = 1;
}
}
int Find(int x) {
return fa[x] == x ? x : fa[x] = Find(fa[x]);
}
void Un(int x, int y) {
int fx = Find(x);
int fy = Find(y);
if (fx == fy) return ;
if (r[fx] < r[fy]) swap(fx, fy);
fa[fy] = fx;
r[fx] += r[fy];
}
map<int, int>m1;
int a[maxn], b[maxn];
struct node {
int id, num; db w1, w2;
bool operator < (const node& _) const {
if ((1.0*w2)/num == (1.0*_.w2)/_.num) return id < _.id;
return (1.0*w2)/num > (1.0*_.w2)/_.num;
}
}e[maxn];
void solve()
{
init();
int n; cin >> n;
int idx = 0;
for (int i = 1 ; i <= n ; i ++) {
int tmp, f1, f2, son;
cin >> tmp >> f1 >> f2;
m1[tmp] = m1[f1] = m1[f2] = 1;
if (f1 != -1) Un(tmp, f1);
if (f2 != -1) Un(tmp, f2);
int k; cin >> k;
for (int j = 1 ; j <= k ; j ++) {
cin >> son; m1[son] = 1;
if (son != -1) Un(tmp, son);
}
cin >> a[tmp] >> b[tmp];
}
for (int i = 0 ; i <= maxn - 4 ; i ++) {
if (!m1[i]) continue;
int idx = Find(i);
if (!e[idx].num) e[idx].id = i; // 不要用id来判断, 因为有0的存在.
else e[idx].id = min(e[idx].id, i);
e[idx].num++;
e[idx].w1 += a[i]; e[idx].w2 += b[i];
}
int k = 0;
for (int i = 0 ; i <= maxn - 4 ; i ++) {
if (!e[i].num) continue;
e[k++] = e[i];
}
sort(e, e+k);
printf("%d\n", k);
for (int i = 0 ; i < k ; i ++) {
printf("%04d %d %.3f %.3f\n", e[i].id, e[i].num, 1.0*e[i].w1/e[i].num, 1.0*e[i].w2/e[i].num);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: