Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
First sanity check: every bridge must cross the river, so the graph has to be bipartite. If it is not bipartite, the answer is instantly .
A valid graph cannot have cycles. In this two-line drawing, a cycle forces an inversion between the two side orders, which means two bridges cross. So for a connected graph, you need .
For a valid tree, ignore leaves for a second. The vertices with degree greater than must form one simple path. If some such vertex touches other non-leaf vertices, the drawing is dead.
Once the non-leaf core is a path, the path itself has only two directions, and the two river sides can be swapped. Leaves attached to the same core vertex are the only freely permutable pieces.
If the tree is a star, handle it separately: choose the center side in ways and order all leaves in ways. Otherwise the answer is where is the number of leaf neighbors of core vertex .
First, kill the impossible cases.
Every bridge must connect opposite sides of the river, so the graph must be bipartite. But even stronger: a valid connected graph cannot contain a cycle. A cycle drawn between two parallel lines forces the order of some pair of edges to flip between the two sides, which means those two bridges cross. Destiny did not merely break Root's love life; it also banned cycles.
So the graph must be a tree. Since the input graph is connected, this is equivalent to:
If not, answer .
What trees are drawable?
Take a tree and look only at vertices with degree greater than . Call them core vertices.
In any valid drawing, these core vertices must form a single simple path.
Why? Suppose a core vertex is connected to three different core-side branches. Each of those branches contains at least one more edge after leaving . In a two-line noncrossing drawing, the branches incident to must occupy non-overlapping intervals. With three real branches, one branch gets trapped between two others, and some edge has to cross to escape. That is the whole obstruction.
So every core vertex may have at most two core neighbors. Since the tree is connected, that means the core is a path.
Leaves are different. A leaf attached to is just one edge, so it can sit in the local bunch next to without causing deeper structure. Leaves attached to the same core vertex can be permuted freely.
Counting
There are two cases.
1. The tree is a star
There is exactly one core vertex: the center. Put the center on either side of the river, then order all leaves on the other side.
So:
This also covers stars with many leaves. For , there is no core vertex, and the answer is simply .
2. The core has at least two vertices
The core path can be oriented left-to-right in ways.
The bipartition sides can be swapped in ways.
For each core vertex , let be the number of leaf neighbors attached to it. Those leaves can be ordered in ways.
Therefore:
where the product is over core vertices.
If any core vertex has more than two core neighbors, output .
Sample sanity checks
For the tree with degrees , the core path has two vertices. The first has leaf, the second has leaves:
For a star with leaves:
Both match.
Algorithm
Precompute factorials up to .
For each test case:
The total work is linear:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
const int MAXN = 200000;
vector<ll> fact(MAXN + 1, 1);
for (int i = 1; i <= MAXN; i++) fact[i] = fact[i - 1] * i % MOD;
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
vector<vector<int>> g(n);
vector<int> deg(n, 0);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
--u; --v;
g[u].push_back(v);
g[v].push_back(u);
deg[u]++;
deg[v]++;
}
if (m != n - 1) {
cout << 0 << '\n';
continue;
}
if (n == 2) {
cout << 2 << '\n';
continue;
}
int coreCnt = 0;
for (int i = 0; i < n; i++) coreCnt += deg[i] > 1;
if (coreCnt == 1) {
cout << 2 * fact[n - 1] % MOD << '\n';
continue;
}
ll ans = 4;
bool ok = true;
for (int v = 0; v < n; v++) {
if (deg[v] == 1) continue;
int coreNeighbors = 0;
int leafNeighbors = 0;
for (int to : g[v]) {
if (deg[to] == 1) leafNeighbors++;
else coreNeighbors++;
}
if (coreNeighbors > 2) ok = false;
ans = ans * fact[leafNeighbors] % MOD;
}
cout << (ok ? ans : 0) << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
const int MAXN = 200000;
vector<ll> fact(MAXN + 1, 1);
for (int i = 1; i <= MAXN; i++) fact[i] = fact[i - 1] * i % MOD;
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
vector<vector<int>> g(n);
vector<int> deg(n, 0);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
--u; --v;
g[u].push_back(v);
g[v].push_back(u);
deg[u]++;
deg[v]++;
}
if (m != n - 1) {
cout << 0 << '\n';
continue;
}
if (n == 2) {
cout << 2 << '\n';
continue;
}
int coreCnt = 0;
for (int i = 0; i < n; i++) coreCnt += deg[i] > 1;
if (coreCnt == 1) {
cout << 2 * fact[n - 1] % MOD << '\n';
continue;
}
ll ans = 4;
bool ok = true;
for (int v = 0; v < n; v++) {
if (deg[v] == 1) continue;
int coreNeighbors = 0;
int leafNeighbors = 0;
for (int to : g[v]) {
if (deg[to] == 1) leafNeighbors++;
else coreNeighbors++;
}
if (coreNeighbors > 2) ok = false;
ans = ans * fact[leafNeighbors] % MOD;
}
cout << (ok ? ans : 0) << '\n';
}
return 0;
}