最近几次的CFF-CSP考试,我发现一个趋势。CSP的第3、4题会与计算机的专业知识密切相关。
例如:化学方程式 – 编译原理,RAID5 – 操作系统。而本题涉及到的是分布式系统的应用(区块链)。
用邻接表储存网络,用FIFO队列保存发送链的信息,即三元组<接收结点的编号,接收的时刻,发送的主链>。
例如,结点1和2相连,结点1在时刻b产生了一个块,结点1的主链变为(0, 1),那么将<结点2,时刻b+t ,主链(0, 1)>
加入队列。
在时刻b时,只要将队列中时刻小于等于b的三元组出队,即发送给相应的结点进行更新即可。因为题目中给的b是升序排列的,因此在队列中所有三元组都是按时间顺序入队的。
遗憾的是,这份代码只得到了80分,猜测原因是入队次数过多,且每次入队都要复制一遍主链。
#include
#include
#include
#include
#include
#include
using namespace std;
/* 发送链的信息 */
struct Message
{
int vertex; // 接收的结点编号
int time; // 预计接收的时间
vector<int> chain; // 主链
Message(int a, int b, vector<int> &c) : vertex(a), time(b), chain(c) {}
};
int n, m, t, k;
vector<vector<int>> G; // 邻接表
vector<vector<int>> chain; // 保存各个结点的主链
queue<Message> que; // Message队列
/* 比较主链src是否能替换掉主链dst */
bool repalce(vector<int> &dst, vector<int> &src)
{
// 若src更长,则可以替换
// 若src和dst一样长,且src最后一块的编号更小,也可以替换
return src.size() > dst.size() || (src.size() == dst.size() && src.back() < dst.back());
}
int main()
{
// 关闭同步
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
G.assign(n + 1, vector<int>()); // 邻接表初始化
chain.assign(n + 1, {0}); // 每个结点的主链初始化为{0}
// 建立邻接表
int x, y;
for (int i = 0; i < m; ++i)
{
cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
cin >> t >> k;
cin.get();
string line;
int a, b, c;
while (k--)
{
// 利用字符串流处理输入
getline(cin, line);
stringstream ss(line);
// 若输入只有两个数,则c会保持值为-1
c = -1;
ss >> a >> b >> c;
// 在时刻b时,处理所有时刻在b之前接收到的主链
while (!que.empty() && que.front().time <= b)
{
int vertex = que.front().vertex; // 结点编号
vector<int> &new_chain = que.front().chain; // 发送出来的主链
if (repalce(chain[vertex], new_chain)) // 如果可以更新
{
chain[vertex] = new_chain; // 则更新结点vertex的主链
for (int v : G[vertex]) // 并且将这条主链推送给它的邻居
que.emplace(v, que.front().time + t, chain[vertex]);
}
que.pop(); // 弹出这个Message
}
if (c == -1) // 如果输入的是2个数(表示一个查询)
{
cout << chain[a].size();
for (int block : chain[a])
cout << ' ' << block;
cout << '\n';
}
else // 如果输入的是3个数(表示产生一个块)
{
chain[a].push_back(c); // 将块放置在主链的末尾
for (int v : G[a]) // 并向邻居推送更新完的主链
que.emplace(v, b + t, chain[a]);
}
}
}
case 1.in
5 10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
1 27
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
1 1
2 1
3 1
4 1
5 1
1 2
2 2
3 2
4 2
5 2
1 10 10
2 11 9
1 11
2 11
3 11
4 11
5 11
1 12
2 12
3 12
4 12
5 12
case 1.out
2 0 1
2 0 2
2 0 3
2 0 4
2 0 5
2 0 1
2 0 1
2 0 1
2 0 1
2 0 1
3 0 1 10
4 0 1 10 9
3 0 1 10
3 0 1 10
3 0 1 10
4 0 1 10 9
4 0 1 10 9
4 0 1 10 9
4 0 1 10 9
4 0 1 10 9
case 2.in
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 28 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
case 2.out
3 0 1 2
2 0 1
1 0
1 0
1 0
3 0 1 2
1 0
1 0
3 0 1 2
2 0 1
2 0 1
2 0 1
4 0 1 2 3
5 0 1 2 3 6
5 0 1 2 3 6
5 0 1 2 3 6
5 0 1 2 3 6
5 0 1 2 3 6
5 0 1 2 3 6
5 0 1 2 3 6
1 0
1 0
如果对您有帮助记得点个赞哟~