[TOC]
7-16 家庭房产
#include <bits/stdc++.h>
using namespace std;
// 并查集
struct DisjointSet {
vector<int> p;
DisjointSet(int n = 1e6) : p(n) { iota(p.begin(), p.end(), 0); }
int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); }
void merge(int x, int y) {
x = find(x), y = find(y);
x < y ? p[y] = x : p[x] = y; // 要保存家庭成员的最小编号,按照编号小的作为父节点合并
}
};
struct Node {
int id, n; // 家庭成员的最小编号 家庭人口数
double house, area; // 人均房产套数 人均房产面积
bool operator<(const Node &t) { return area != t.area ? area > t.area : id < t.id; }
};
int main() {
DisjointSet ds;
set<int> peo; // 保存每一个人的编号
map<int, pair<int, int>> property; // 保存每一个人的房产
int n;
cin >> n;
while (n--) {
int x, fa, ma, k, son, a, b;
cin >> x >> fa >> ma >> k;
// 输入之后,保存每个人的编号,并把家庭成员[自己,父,母,孩子]连接在一个并查集里
peo.insert(x);
if (fa != -1) {
ds.merge(x, fa);
peo.insert(fa);
}
if (ma != -1) {
ds.merge(x, ma);
peo.insert(ma);
}
while (k--) {
cin >> son;
ds.merge(x, son);
peo.insert(son);
}
cin >> a >> b;
property[x] = {a, b};
}
map<int, vector<int>> family; // 家庭成员的最小编号--家庭成员
for (int i : peo) {
family[ds.find(i)].push_back(i); // find(i)为i的家庭中的最小编号,把i加入这个家庭
}
vector<Node> ans;
for (auto &[id, people] : family) {
double a = 0, b = 0;
// people为这和家庭的所有成员,累加他们的所有资产,并计算平均值
for (int x : people) {
a += property[x].first;
b += property[x].second;
}
a /= people.size();
b /= people.size();
ans.push_back(Node{id, int(people.size()), a, b}); // 家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积
}
sort(ans.begin(), ans.end());
cout << ans.size() << endl;
for (auto &e : ans) {
printf("%04d %d %.3lf %.3lf\n", e.id, e.n, e.house, e.area);
}
return 0;
}7-23 图着色问题
#include <bits/stdc++.h>
using namespace std;
using Edge = pair<int, int>;
int n, m, k, T;
vector<Edge> G; // 存储边目录
int main() {
cin >> n >> m >> k;
for (int i = 0, u, v; i < m; i++) {
cin >> u >> v;
G.push_back({u, v});
}
cin >> T;
while (T--) {
vector<int> color(n + 1);
set<int> st;
for (int i = 1; i <= n; i++) {
cin >> color[i];
st.insert(color[i]);
}
// 一个匿名函数
auto OK = [&]() {
// 图染色数不是k,则方案不正确
if (st.size() != k)
return false;
for (auto &[u, v] : G)
if (color[u] == color[v]) // 存在两个相邻顶点具有同一种颜色,方案不正确
return false;
return true;
};
puts(OK() ? "Yes" : "No");
}
}7-30 深入虎穴
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
vector<int> G[N];
bool vis[N];
int indeg[N], dep[N]; // dep[u]为u结点到起点距离,也就是u的深度
int n, m;
int mx, idx;
void bfs(int s) {
queue<int> q;
q.push(s);
dep[s] = 1;
mx = 1, idx = s; // 存储最深结点编号以及它的深度
while (!q.empty()) {
int u = q.front();
q.pop();
if (vis[u])
continue;
vis[u] = true;
for (int v : G[u]) {
q.push(v);
dep[v] = dep[u] + 1; // bfs搜索,子节点的深度为父节点的深度+1
if (mx < dep[v])
mx = dep[v], idx = v; // 更新最深结点
}
}
}
int main() {
cin >> n;
for (int u = 1; u <= n; u++) {
int sz, v;
cin >> sz;
while (sz--) {
cin >> v;
indeg[v]++;
G[u].push_back(v);
}
}
int s = find(indeg + 1, indeg + n + 1, 0) - indeg; // 查找入度为0的结点,即为起点
bfs(s);
cout << idx;
}7-86 宿舍谁最高?
#include <bits/stdc++.h>
using namespace std;
struct Node {
string name;
int height, weight;
};
map<int, Node> mp;
int main() {
int n;
cin >> n;
while (n--) {
int num, height, weight;
string name;
cin >> num >> name >> height >> weight;
// 如果这个宿舍还没往里面加人,或者宿舍里这个人的身高不如当前这个人高,更新这个宿舍的最高人
if (!mp.count(num) || mp[num].height < height)
mp[num] = Node{name, height, weight};
}
// map按照键值的大小排序,也就是按照宿舍号升序排
for (auto &[k, e] : mp) {
printf("%06d %s %d %d\n", k, e.name.c_str(), e.height, e.weight);
}
return 0;
}7-93 秀恩爱分得快
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, m;
double G[N][N];
vector<int> peo[N]; // 存储每个人在哪些照片出现过
vector<int> photo[N]; // 存储每张照片有哪些人
bool sex[N]; // 性别
string id[N]; // 编号
// 获取每个人的编号
int getId(string &s) {
int x = abs(stoi(s));
sex[x] = s[0] == '-';
id[x] = s;
return x;
}
int main() {
cin >> n >> m;
for (int i = 1, k; i <= m; i++) {
cin >> k;
for (int j = 0; j < k; j++) {
string num;
cin >> num;
int x = getId(num);
peo[x].push_back(i);
photo[i].push_back(x); // 每插入一个人,双向地记录人与照片、照片与人的关系
}
}
string A, B;
cin >> A >> B;
int a = getId(A), b = getId(B);
// 计算用户 A 和 B 的异性朋友的亲密度
for (int u : {a, b})
for (int i : peo[u])
for (int v : photo[i])
if (sex[u] != sex[v])
G[u][v] += 1.0 / photo[i].size();
// 查找最亲密的异性朋友的亲密度
double mxa = 0, mxb = 0;
for (int i = 0; i < n; i++)
if (sex[i] != sex[a])
mxa = max(mxa, G[a][i]);
for (int i = 0; i < n; i++)
if (sex[i] != sex[b])
mxb = max(mxb, G[b][i]);
// 如果 A 和 B 正是彼此亲密度最高的一对,则只输出他们的编号
if (G[a][b] == mxa && G[b][a] == mxb) {
cout << id[a] << " " << id[b] << endl;
return 0;
} else { // 按他们编号的绝对值递增输出
for (int i = 0; i < n; ++i)
if (G[a][i] == mxa && sex[a] != sex[i])
cout << id[a] << " " << id[i] << endl;
for (int i = 0; i < n; ++i)
if (G[b][i] == mxb && sex[b] != sex[i])
cout << id[b] << " " << id[i] << endl;
}
return 0;
}