1034 Head of a Gang

1034 Head of a Gang

题目大意

根据对应的一对姓名和通话时长,合并成几簇,并筛选出符合条件的几簇。

算法思想

  • 这道题看起来很简单,但是写起来真的麻烦,也可能是我没用并查集,导致出现一些致命的错误,最后花了很长时间去改
  • 我的代码是在输入时就去创建簇,并添加到簇集合,主要是加入簇时比较麻烦,写了都有70行左右,需要找到已对应的簇,或者创建新的簇,或者合并新的簇(主要是这个难做),测试点4就需要合并

代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct node {
	string name;
	int weight;
};
struct cluster {
	vector<node>mem;
	int sum = 0, num = 0, head = 0;
};
vector<cluster>list;
bool cmp(cluster a, cluster b) {//比较函数
	return a.mem[a.head].name < b.mem[b.head].name;
}
void add(string a, string b, int u) {//向簇中加元素
	bool flag = false, flag1 = false, flag2 = false;
	int wb=-1, wa=-1;
	for (int i = 0; i < list.size(); i++) {//先遍历簇
		for (int j = 0; j < list[i].mem.size(); j++) {//再遍历簇中的结点成员
			if (list[i].mem[j].name == a || list[i].mem[j].name == b) {//在簇中找到已存在的相同元素
				flag = true;
				if (list[i].mem[j].name == a) {//找到a字符串时
					list[i].mem[j].weight += u;//改变结点权重
					if (list[i].mem[j].weight > list[i].mem[list[i].head].weight)//更新最大权重的head
						list[i].head = j;
					if (list[i].mem[j].weight == list[i].mem[list[i].head].weight && list[i].mem[j].name < list[i].mem[list[i].head].name)//更新字符串更小的head
						list[i].head = j;
					flag1 = true;
					wa = i;
				}
				if (list[i].mem[j].name == b) {//找到b字符串
					list[i].mem[j].weight += u;
					if (list[i].mem[j].weight > list[i].mem[list[i].head].weight)
						list[i].head = j;
					if (list[i].mem[j].weight == list[i].mem[list[i].head].weight && list[i].mem[j].name < list[i].mem[list[i].head].name)
						list[i].head = j;
					flag2 = true;
					wb = i;
				}
			}
		}
		
	}
	if (!flag) {//没有找到对应的簇,创建新簇
		cluster c;
		node d, e;
		d.name = a;
		d.weight = u;
		e.name = b;
		e.weight = u;
		c.mem.push_back(d);
		c.mem.push_back(e);
		c.num += 2;
		c.sum += u;
		list.push_back(c);
	}
	else {//找到对应簇
		if (flag1 && flag2) {//a,b字符串都已对应
			if (wa == wb) {//属于统一簇
				list[wa].sum += u;
			}
			else {//不属于统一簇,需要合并簇
				list[wa].num += list[wb].num;
				list[wa].sum = list[wa].sum + list[wb].sum + u;
				if (list[wa].mem[list[wa].head].weight < list[wb].mem[list[wb].head].weight)//更新head位置
					list[wa].head += list[wb].head + 1;
				list[wa].mem.insert(list[wa].mem.end(), list[wb].mem.begin(), list[wb].mem.end());//插入到list[wa]的mem后面
				list.erase(list.begin() + wb);//删除wb位置
			}
		}
		if (!flag1) {//没找到a字符串对应,但是b字符串已对应,将a加入到b簇中
			list[wb].num++;
			node d;
			d.name = a;
			d.weight = u;
			list[wb].sum += u;
			list[wb].mem.push_back(d);
		}
		if (!flag2) {//将b加入到a簇中
			list[wa].num++;
			node d;
			d.name = b;
			d.weight = u;
			list[wa].sum += u;
			list[wa].mem.push_back(d);
		}
	}
	return;
}
int main() {
	int n, k, u, m = 0;
	string a, b;
	cin >> n >> k;
	for (int i = 0; i < n; i++) {
		cin >> a >> b >> u;
		add(a, b, u);//创建簇
	}
	sort(list.begin(), list.end(), cmp);//排序
	for (int i = 0; i < list.size(); i++) {//找到合适的簇
		if (list[i].sum > k && list[i].num>2)
			m++;
	}
	cout << m << endl;
	for (int i = 0; i < list.size(); i++) {
		if(list[i].sum>k && list[i].num>2)
			cout << list[i].mem[list[i].head].name << " " << list[i].num << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值