CCF 2019-12-4 区块链 100分

CCF 2019-12-4 区块链 100分

题目大意

分布式网络(图)中n个节点通过m条边相互连接,每个节点自己维护一个主链,主链自带一个创世块"0",任意节点的主链更新后都要将自己的主链发送给相邻的节点更新其主链,发送的信息存在t的时延

  • 接受更新规则
    • 主链长则更新
    • 主链长度相等并且最后一块小则更新

输入一个n个节点的图n<=500
有m条边m<=10000
有两种指令

  • 长度为2的是查询指令,输出t时间下n节点的主链
  • 长度为3的是产生指令,在t时间将编号m的块放到n节点主链末端

解题思路

用邻接表保存网络

vector<vector<int>> adjList;

每个节点维护一条主链

vector<vector<int>> linkLists;

使用一个任务队列来维护发送的更新信息
ps:map方便维护更新队列时间的序,操作也比优先队列舒服
从左到右表示更新时间,更新节点,发送的主链

map<int, unordered_map<int, vector<int>>> taskQueue;

主要逻辑
产生的任务保存在任务队列中
当每一条执行指令时把任务时间等于或者小于当前时间的任务取出执行
当有主链变化的时候产生任务
注意添加限制条件剪除多余的任务否则会超时
不懂的欢迎留言

代码

// 区块链.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <queue>
#include<map>
#include<unordered_map>
using namespace std;
int n, m;
int t, k;
vector<vector<int>> adjList;
vector<vector<int>> linkLists;

map<int, unordered_map<int, vector<int>>> taskQueue;

void send(int time, int node_p) {
	auto& rightList = linkLists[node_p];
	for (const int& ele : adjList[node_p]) {
		auto& leftList = linkLists[ele - 1];

		if (leftList.size() < rightList.size() ||
			leftList.size() == rightList.size() && leftList.back() > rightList.back())//必须比目标链表更优
		{
			auto& task = taskQueue[time + t][ele];
			if (task.empty() ||
				task.size() < rightList.size() ||
				task.size() == rightList.size() && task.back() > rightList.back())//如果有同一时间同一目标的任务必须比该任务中的链表更优
				task = rightList;//更新或添加任务
		}
	}
}

void update() {
	int time = taskQueue.begin()->first;
	for (const auto& x : taskQueue[time]) {
		int node_p = x.first - 1;
		auto& rightList = x.second;
		auto& leftList = linkLists[node_p];
		if (leftList.size() < rightList.size() ||
			leftList.size() == rightList.size() && leftList.back() > rightList.back())//
		{
			leftList = rightList;
			send(time, node_p);
		}
	}
	taskQueue.erase(time);
}

void executeCommands(const vector<vector<int>>& commands) {
	for (int i = 0; i < k; ++i) {
		int node_p = commands[i][0] - 1, time = commands[i][1];
		while (!taskQueue.empty() && time >= taskQueue.begin()->first)
			update();

		if (commands[i].size() == 2) {//查询命令
			cout << linkLists[node_p].size();
			for (auto& ele : linkLists[node_p])
				cout << " " << ele;
			cout << endl;
		}
		else if (commands[i].size() == 3) {//产生命令
			int number = commands[i][2];
			linkLists[node_p].push_back(number);
			send(time, node_p);
		}
	}
}

//#define DEBUG

int main()
{
#ifdef DEBUG
	fstream cin("input.txt");
#endif // DEBUG

	cin >> n >> m;
	adjList.resize(501);
	linkLists.resize(n, { 0 });
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		adjList[u - 1].push_back(v);
		adjList[v - 1].push_back(u);
	}
	cin >> t >> k;
	vector<vector<int>> commands;
	cin.get();//读取回车
	for (int i = 0; i < k; ++i) {
		stringstream strs;
		string str;
		getline(cin, str);
		strs << str;
		int x;
		vector<int> tempv;
		while (strs >> x)
			tempv.push_back(x);
		commands.push_back(tempv);
	}

	executeCommands(commands);
}
/*
15 13
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
1 10
10 11
11 12
12 13
14 15
6 28
1 1 1
1 2 2
1 6
2 7
13 7
9 7
5 7
3 14
8 14
5 14
11 14
9 25
5 25
13 25
9 29 3
5 29 4
13 29 5
1 53
2 59 6
2 59
1 1000
3 1000
8 1000
9 1000
10 1000
13 1000
14 1000
15 1000
*/

题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了1 篇原创文章 · 获赞 1 · 访问量 49

猜你喜欢

转载自blog.csdn.net/qq_41433566/article/details/105211580