【1034 30 dfs 连通块】 Head of a Gang
传送门
题意
一共 \(n\) 条边,每条边为 \((s_{1},s_{2},w)\),如果一个连通块内节点个数 \(> 2\),并且每个点的所有度都大于给定的 \(k\) ,那么认为这个连通块构成一个 \(gang\),度最大的为帮派首脑,求出帮派的首脑以及帮派具体人数
数据范围
\(n,k\leq 1000\)
题解
- 并查集做法
- 将每条边的两个点合并,记录每个点的值,边的起始和终止都加边权
- 遍历所有节点,将当前节点的根加上当前值,节点个数增加,如果当前值大于
head更新 - 遍历所有节点,如果是根判断当前集合的节点个数是否大于 2,判断值是否满足,因为每个节点的起始和终止都计算了所以要比较
k * 2
dfs做法- 遍历每个连通块同时进行计算,对于每条边的权值都计算到当前块内即可
- 每条边的两个都加上权重,不影响找最大值
Code
- 并查集
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 3010;
vector<int> fa(N), Time(N), heads(N), tot(N), numbers(N);
int id = 1;
unordered_map<string, int> name_id;
unordered_map<int, string> id_name;
int get(string name) {
if (not name_id[name]) name_id[name] = id++;
return name_id[name];
}
int find(int u) {
if (fa[u] != u) fa[u] = find(fa[u]);
return fa[u];
}
void unionSet(int u, int v) {
int pu = find(u), pv = find(v);
fa[pu] = pv;
}
int main() {
int n, k; cin >> n >> k;
iota(fa.begin(), fa.end(), 0);
iota(heads.begin(), heads.end(), 0);
for (int i = 0; i < n; i++) {
string u, v; int w;
cin >> u >> v >> w;
int id_u = get(u), id_v = get(v);
id_name[id_u] = u;
id_name[id_v] = v;
unionSet(id_u, id_v);
Time[id_u] += w;
Time[id_v] += w;
}
for (int i = 1; i < id; i++) {
int root = find(i);
numbers[root]++;
tot[root] += Time[i];
if (Time[heads[root]] < Time[i]) heads[root] = i;
}
vector<pair<string, int>> ans;
for (int i = 1; i < id; i++) {
if (fa[i] == i and numbers[i] > 2 and tot[i] > k * 2) {
ans.push_back({id_name[heads[i]], numbers[i]});
}
}
sort(ans.begin(), ans.end());
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++) {
if (i) cout << endl;
cout << ans[i].first << ' ' << ans[i].second;
}
}
dfs
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
struct Edge {
int to, w;
};
int id = 1;
unordered_map<string, int> name_id;
unordered_map<int, string> id_name;
vector<bool> st(N);
vector<vector<Edge>> edge(N);
vector<int> degree(N);
int get(string name) {
if (not name_id[name]) name_id[name] = id++;
id_name[name_id[name]] = name;
return name_id[name];
}
void dfs(int u, int& head, int& tot, int& num) {
st[u] = true;
num++;
if (degree[u] > degree[head]) head = u;
for (auto& e : edge[u]) {
tot += e.w;
if (not st[e.to]) dfs(e.to, head, tot, num);
}
}
int main() {
int n, k; cin >> n >> k;
for (int i = 0; i < n; i++) {
string u, v; int w;
cin >> u >> v >> w;
int id_u = get(u), id_v = get(v);
edge[id_u].push_back({id_v, w});
degree[id_u] += w;
degree[id_v] += w;
}
vector<pair<string, int>> ans;
for (int i = 1; i < id; i++) {
if (not st[i]) {
int head = i, tot = 0, num = 0;
dfs(i, head, tot, num);
if (num > 2 and tot > k) {
ans.push_back({id_name[head], num});
}
}
}
sort(ans.begin(), ans.end());
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++) {
if (i) cout << endl;
cout << ans[i].first << ' ' << ans[i].second;
}
}

浙公网安备 33010602011771号