【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;
	}
}

posted @ 2021-02-19 22:20  Hyx'  阅读(55)  评论(0)    收藏  举报