图中的最短路径查询
Shortest path queries in a graph
我们得到了一个包含 N
个节点的静态 graph,其中我们有 edges,如下所示:
1. node-1 to node-i (for all 2 <= i <= N) of weight N + 1.
2. node-x to node-y (for all 2 <= x,y <= N) of weight 1, if and only if x divides y OR y divides x.
我们得到 Q
类型 (u, v)
的查询,我们需要找到节点 u
和 v.
之间的最短路径
约束:
T <= 10^5 // number of test cases
N <= 2 * 10^5 // number of nodes
Q <= 2 * 10^5 // number of queries
u,v <= N
方法:几乎恒定时间 - O(1)。
private int gcd(int x, int y) {
if(x % y == 0) return y;
return gcd(y, x % y);
}
private int lcm(int x, int y) {
return (x * y) / gcd(x, y);
}
private int[] shortest_path(int N, int Q, int[][] queries) {
int[] result = new int[Q];
int[] smallestDivisor = new int[N + 1];
for(int i = 2; i <= N; i++) {
if(smallestDivisor[i] == 0) {
int f = 1;
while(i * f <= N) {
if(smallestDivisor[i * f] == 0)
smallestDivisor[i*f] = i;
f += 1;
}
}
}
for(int i = 0; i < Q; i++) {
int u = queries[i][0];
int v = queries[i][1];
int LCM = lcm(u, v);
int GCD = gcd(u, v);
int smallestDivisorOfU = smallestDivisor[u];
int smallestDivisorOfV = smallestDivisor[v];
if(u == v)
result[i] = 0; // if nodes are same
else if(u == 1 || v == 1)
result[i] = N + 1; // if any of the node is '1'
else if(u % v == 0 || v % u == 0)
result[i] = 1; // if nodes are divisible
else if(GCD != 1 || LCM <= N)
result[i] = 2; // if gcd != 1 || lcm exists thus we can go as: 'x' --> gcd(x, y)/lcm(x,y) --> 'y' : 2 distance
else if(Math.min(smallestDivisorOfU * v, smallestDivisorOfV * u) <= N)
result[i] = 3;
else
result[i] = 2 * (N + 1); // we have to go via '1' node
}
return result;
}
Will this approach work for every test case?
在 LCM 之前添加 GCD 计算以提供路径 A => GCD(A,B) => B
(完成)
当LCM检查失败时,对值进行分解。如果它们是质数,则移动通过 "1"
节点。否则检查
if (min(SmallestDivisorOfA * B , SmallestDivisorOfB * A) <= N)
result[i] = 3;
Example: 7=>14=>2=>6
我们得到了一个包含 N
个节点的静态 graph,其中我们有 edges,如下所示:
1. node-1 to node-i (for all 2 <= i <= N) of weight N + 1.
2. node-x to node-y (for all 2 <= x,y <= N) of weight 1, if and only if x divides y OR y divides x.
我们得到 Q
类型 (u, v)
的查询,我们需要找到节点 u
和 v.
约束:
T <= 10^5 // number of test cases
N <= 2 * 10^5 // number of nodes
Q <= 2 * 10^5 // number of queries
u,v <= N
方法:几乎恒定时间 - O(1)。
private int gcd(int x, int y) {
if(x % y == 0) return y;
return gcd(y, x % y);
}
private int lcm(int x, int y) {
return (x * y) / gcd(x, y);
}
private int[] shortest_path(int N, int Q, int[][] queries) {
int[] result = new int[Q];
int[] smallestDivisor = new int[N + 1];
for(int i = 2; i <= N; i++) {
if(smallestDivisor[i] == 0) {
int f = 1;
while(i * f <= N) {
if(smallestDivisor[i * f] == 0)
smallestDivisor[i*f] = i;
f += 1;
}
}
}
for(int i = 0; i < Q; i++) {
int u = queries[i][0];
int v = queries[i][1];
int LCM = lcm(u, v);
int GCD = gcd(u, v);
int smallestDivisorOfU = smallestDivisor[u];
int smallestDivisorOfV = smallestDivisor[v];
if(u == v)
result[i] = 0; // if nodes are same
else if(u == 1 || v == 1)
result[i] = N + 1; // if any of the node is '1'
else if(u % v == 0 || v % u == 0)
result[i] = 1; // if nodes are divisible
else if(GCD != 1 || LCM <= N)
result[i] = 2; // if gcd != 1 || lcm exists thus we can go as: 'x' --> gcd(x, y)/lcm(x,y) --> 'y' : 2 distance
else if(Math.min(smallestDivisorOfU * v, smallestDivisorOfV * u) <= N)
result[i] = 3;
else
result[i] = 2 * (N + 1); // we have to go via '1' node
}
return result;
}
Will this approach work for every test case?
在 LCM 之前添加 GCD 计算以提供路径
A => GCD(A,B) => B
(完成)当LCM检查失败时,对值进行分解。如果它们是质数,则移动通过
"1"
节点。否则检查
if (min(SmallestDivisorOfA * B , SmallestDivisorOfB * A) <= N)
result[i] = 3;
Example: 7=>14=>2=>6