Submission #1230507

#TimeUsernameProblemLanguageResultExecution timeMemory
1230507hashdfdfhToll (BOI17_toll)C++20
100 / 100
715 ms79176 KiB
#include <bits/stdc++.h> using namespace std; const int MAX_N = 5e4 + 5; const int MAX_K = 5; int k, n, m, q; // 最大级别数,数值/k相同的放在一个层级 int level; // 第一个维度:起始点所在级别 // 第二个维度:起始级别节点编号(%k结果) // 第三个维度:目标级别节点编号(%k结果) // 第四个维度:目标点所在级别(第一个维度 + 2^ 第四个维度 - 1) int dat[MAX_N][MAX_K][MAX_K][16]; void build() { // 最多有n/k层 n = n / k; level = log2(n); // 初始化表格 // 计算每个长度是2^j的区间 for (int j = 1; j <= level; j++) { for (int i = 0; i + (1 << j) <= n; i++) { // 需要求的级别区间:[i, i + 2 ^ j - 1] // 左侧区间:开始是i,长度是2^(j-1) [i, i + 2 ^ (j - 1) - 1] // 右侧区间:开始是i + 2 ^ (j - 1),长度是2^(j-1) [i + 2 ^ (j - 1), i + 2 ^ j - 1] // 枚举左侧级别的每个节点编号 for (int u = 0; u < k; u++) { // 枚举右侧级别的每个节点编号 for (int v = 0; v < k; v++) { // 枚举中间级别的每个节点编号,作为中继点 for (int p = 0; p < k; p++) { // 第i个级别的第u个节点,到第i + 2 ^ j - 1个级别的第p个节点 // 第i + 2 ^ j个级别的第p个节点,到第i + 2 ^ j - 1个级别的第v个节点 int tmp = dat[i][u][p][j - 1] + dat[i + (1 << (j - 1))][p][v][j - 1]; dat[i][u][v][j] = min(dat[i][u][v][j], tmp); } } } } } } void query(int a, int b) { // a所在层级 int alevel = a / k; // b所在层级 int blevel = b / k; // a所在层级节点编号 int ano = a % k; // b所在层级节点编号 int bno = b % k; // 计算两个层级的差距 int dif = blevel - alevel; // 第一个维度:0表示前一轮结果,1表示当前轮结果 // 第二个维度:该层级的第no个点 int tmp[2][MAX_N]; memset(tmp, 0x3F, sizeof(tmp)); tmp[0][ano] = 0; // 获取dif二进制上每一个1 for (int i = 0; (1 << i) <= dif; i++) { // 如果第i位是1 if ((1 << i) & dif) { // 计算第alevel级别的ano个点,到第alevel + 2^i 级别的每个节点 // 最短距离是多少 // 初始化当前轮次结果 memset(tmp[1], 0x3F, sizeof(tmp[1])); // 计算到当前层级的第u个节点 for (int u = 0; u < k; u++) { // 从前一轮次的第v个节点过来 for (int v = 0; v < k; v++) { tmp[1][u] = min(tmp[1][u], tmp[0][v] + dat[alevel][v][u][i]); } } // 更新tmp[0]为tmp[1]的结果 memcpy(tmp[0], tmp[1], sizeof(tmp[0])); // alevel去往后面的层级 alevel += (1 << i); } } // 如果仍然是最大值,那么就是-1 if (tmp[0][bno] == 0x3F3F3F3F) { cout << -1 << endl; } else { cout << tmp[0][bno] << endl; } } int main() { // 读取数据 cin >> k >> n >> m >> q; // 初始化为一个很大的数值 memset(dat, 0x3F, sizeof(dat)); // 读取m条边信息 int a, b, c; for (int i = 0; i < m; ++i) { cin >> a >> b >> c; // a所在层级 int alevel = a / k; // b所在层级(一定是a+1) // a所在层级节点编号 int ano = a % k; // b所在层级节点编号 int bno = b % k; // 最后一个维度是0,代表alevel到alevel+1 dat[alevel][ano][bno][0] = c; } // 初始化表格数据 build(); // 读取q次查询 for (int i = 0; i < q; ++i) { cin >> a >> b; query(a, b); } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...