#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
ll modpow(ll a, ll e) {
ll r = 1 % MOD;
a %= MOD;
while (e > 0) {
if (e & 1) r = (r * a) % MOD;
a = (a * a) % MOD;
e >>= 1;
}
return r;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
const string NAME = "coloring";
// If running with file io:
// freopen((NAME + ".inp").c_str(), "r", stdin);
// freopen((NAME + ".out").c_str(), "w", stdout);
int n, m, k;
if (!(cin >> n >> m >> k)) return 0;
// adjacency: pair (neighbor, edgeIndex)
vector<vector<pair<int,int>>> adj(n+1);
for (int i = 1; i <= n-1; ++i) {
int u, v; cin >> u >> v;
adj[u].push_back({v, i});
adj[v].push_back({u, i});
}
// parent, height and edgeToParent arrays (size n+1)
vector<int> parent(n+1, 0), height(n+1, 0), edgeToParent(n+1, 0);
// do DFS / stack to set parent, height, edgeToParent
{
stack<int> st;
st.push(1);
parent[1] = 0;
height[1] = 0;
while (!st.empty()) {
int u = st.top(); st.pop();
for (auto [v, ei] : adj[u]) {
if (v == parent[u]) continue;
parent[v] = u;
edgeToParent[v] = ei; // edge index between v and parent[v]
height[v] = height[u] + 1;
st.push(v);
}
}
}
// read m queries, for each build vector of edge indices along path
vector<vector<int>> path(m);
for (int i = 0; i < m; ++i) {
int u, v; cin >> u >> v;
vector<int> edges_up, edges_down;
// raise deeper node
while (height[u] > height[v]) {
edges_up.push_back(edgeToParent[u]);
u = parent[u];
}
while (height[v] > height[u]) {
edges_down.push_back(edgeToParent[v]);
v = parent[v];
}
// now same height
while (u != v) {
edges_up.push_back(edgeToParent[u]);
edges_down.push_back(edgeToParent[v]);
u = parent[u];
v = parent[v];
}
// path edges = edges_up followed by reverse(edges_down)
path[i] = edges_up;
for (int j = (int)edges_down.size() - 1; j >= 0; --j) path[i].push_back(edges_down[j]);
}
// quick check: if any path has < 1 edge then impossible? The original checked <2 because they stored edges differently.
// For safety: if path empty (u==v) then this query contributes no edges; depending on problem statement that might be invalid.
for (int i = 0; i < m; ++i) {
if ((int)path[i].size() < 1) {
cout << 0 << '\n';
return 0;
}
}
// initial answer: k^(n-1) (color edges independently)
ll sol = modpow(k, n - 1);
// safety note: exponential in m. If m > 22 this loop is heavy. Assume problem constraints allow 2^m brute-force.
if (m >= 60) {
// extremely unlikely per problem constraints; but avoid UB with (1LL<<m)
cerr << "Warning: m is large, brute-force over 2^m is infeasible/unsafe\n";
}
int totalMasks = 1 << m; // assume m <= 30-ish per constraints
for (int mask = 1; mask < totalMasks; ++mask) {
// build graph among edges (1..n-1) using selected paths
vector<vector<int>> g1(n); // index by edge index (1..n-1). size n is enough
vector<char> seen(n, 0); // seen[edgeIndex]
for (int i = 0; i < m; ++i) if (mask & (1<<i)) {
auto &vec = path[i];
for (int j = 0; j + 1 < (int)vec.size(); ++j) {
int a = vec[j], b = vec[j+1];
g1[a].push_back(b);
g1[b].push_back(a);
}
}
// count connected components among edges 1..n-1 that are considered as graph nodes
int cnt = 0;
for (int e = 1; e <= n-1; ++e) {
if (!seen[e]) {
// but if no adjacency and also not present in any selected path, it is a singleton component
++cnt;
// DFS
stack<int> st; st.push(e); seen[e] = 1;
while (!st.empty()) {
int x = st.top(); st.pop();
for (int y : g1[x]) if (!seen[y]) {
seen[y] = 1;
st.push(y);
}
}
}
}
int bits = __builtin_popcount((unsigned)mask);
if (bits % 2 == 0) sol = (sol + modpow(k, cnt)) % MOD;
else sol = (sol - modpow(k, cnt) + MOD) % MOD;
}
cout << sol << '\n';
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |