G - Return to 1 Editorial by en_translator
First of all, the vertices not reachable from vertex and those from which vertex is not reachable (and the adjacent edges) can be removed from the graph. We now assume that the graph is strongly connected.
Let be the set of sizes of lengths of cycles containing vertex , and be the greatest common divisors of the numbers contained in (or if is an empty set). Then, the answer is Yes
if and only if is a divisor of .
Proof
Suppose that there are two cycles of lengths and . Also, suppose that , where and . Then, for all integers , there exist non-negative integers and such that . Thus, by using the two cycles together, we can construct any cycle of a length that is a multiple of and is at least . As an extension, by using cycles of lengths , and , we can construct any cycle of a length that is a multiple of and is at least , which can be shown by induction. Since is sufficiently large, if is a divisor of , then a cycle of length exists. Conversely, if has a prime divisor other than and , then it is obvious that there is no cycle of a length that is a multiple of . Thus, the proposition is proven.
However, can be an infinite set, so we cannot find . Now, (it is a bit sudden) let us take an arbitrary directed spanning tree rooted at vertex , and let be the depth of vertex in . Then, for all integers , the following fact holds:
Proof
() We show the contraposition. Since for all edges , the sequence of on the cycle that starts from and ends at vertex is always periodic, like . Thus, for all .
() Take a cycle that contains an edge such that exactly once, and let be its length. (Since every edge in satisfies , such a cycle always exists.) Then, .
Hence, if we let be the greatest common divisor of for all edges , then coincides with . Since can be found in a total of time, the problem has been solved.
Sample code (C++):
#include<bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<vector<int>> G(n), rG(n);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
--u, --v;
G[u].push_back(v);
rG[v].push_back(u);
}
vector<int> dep(n, -1);
dep[0] = 0;
auto dfs = [&](auto &dfs, int u) -> void {
for (int v: G[u]) {
if (dep[v] != -1) continue;
dep[v] = dep[u] + 1;
dfs(dfs, v);
}
};
dfs(dfs, 0);
vector<bool> valid(n); // valid[i] = i から 0 に到達可能かどうか
auto dfs_r = [&](auto &dfs_r, int u) -> void {
valid[u] = true;
for (int v: rG[u]) {
if (valid[v]) continue;
dfs_r(dfs_r, v);
}
};
dfs_r(dfs_r, 0);
for (int i = 0; i < n; i++) if (!valid[i]) dep[i] = -1;
int g = 0;
for (int u = 0; u < n; u++) {
if (dep[u] == -1) continue;
for (int v: G[u]) {
if (dep[v] == -1) continue;
g = gcd(g, abs(dep[u] + 1 - dep[v]));
}
}
if (!g) {
cout << "No\n";
continue;
}
while (g % 2 == 0) g /= 2;
while (g % 5 == 0) g /= 5;
cout << (g == 1 ? "Yes" : "No") << '\n';
}
}
#include<bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t--) { int n, m; cin >> n >> m; vector<vector<int>> G(n), rG(n); for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; --u, --v; G[u].push_back(v); rG[v].push_back(u); } vector<int> dep(n, -1); dep[0] = 0; auto dfs = [&](auto &dfs, int u) -> void { for (int v: G[u]) { if (dep[v] != -1) continue; dep[v] = dep[u] + 1; dfs(dfs, v); } }; dfs(dfs, 0); vector<bool> valid(n); // valid[i] = i から 0 に到達可能かどうか auto dfs_r = [&](auto &dfs_r, int u) -> void { valid[u] = true; for (int v: rG[u]) { if (valid[v]) continue; dfs_r(dfs_r, v); } }; dfs_r(dfs_r, 0); for (int i = 0; i < n; i++) if (!valid[i]) dep[i] = -1; int g = 0; for (int u = 0; u < n; u++) { if (dep[u] == -1) continue; for (int v: G[u]) { if (dep[v] == -1) continue; g = gcd(g, abs(dep[u] + 1 - dep[v])); } } if (!g) { cout << "No\n"; continue; } while (g % 2 == 0) g /= 2; while (g % 5 == 0) g /= 5; cout << (g == 1 ? "Yes" : "No") << '\n'; } }
posted:
last update: