제출 #1277281

#제출 시각아이디문제언어결과실행 시간메모리
1277281hotaruuUsmjeri (COCI17_usmjeri)C++20
0 / 140
210 ms80668 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 300005;
const int LOG = 20;
const int MOD = 1e9 + 7;

int n, m;
vector<int> g[MAXN];
int up[MAXN][LOG], depth[MAXN];
int high[MAXN];
int color[MAXN];
vector<pair<int,int>> logic[MAXN]; // đồ thị logic (v, parity)

// ========== LCA ==========
void dfs_lca(int u, int p) {
    up[u][0] = p;
    for (int i = 1; i < LOG; i++)
        up[u][i] = up[up[u][i - 1]][i - 1];
    for (int v : g[u]) if (v != p) {
        depth[v] = depth[u] + 1;
        dfs_lca(v, u);
    }
}

int lca(int a, int b) {
    if (depth[a] < depth[b]) swap(a, b);
    int diff = depth[a] - depth[b];
    for (int i = LOG - 1; i >= 0; i--)
        if (diff >> i & 1) a = up[a][i];
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (up[a][i] != up[b][i]) {
            a = up[a][i];
            b = up[b][i];
        }
    }
    return up[a][0];
}

// ========== Cập nhật ràng buộc ==========
void add_path(int a, int b) {
    int c = lca(a, b);
    high[a]++;
    high[b]++;
    high[c] -= 2;
}

// ========== Duyệt cây, cộng dồn high và tạo đồ thị logic ==========
void connect(int u, int p) {
    for (int v : g[u]) if (v != p) {
        connect(v, u);
        if (high[v] > 0) {
            // Cạnh (u, v) nằm trong ít nhất một đường ràng buộc
            logic[u].push_back({v, 0});
            logic[v].push_back({u, 0});
        }
        high[u] += high[v];
    }
}

// ========== DFS tô màu (0/1) để kiểm tra mâu thuẫn ==========
bool dfs_color(int u, int c) {
    color[u] = c;
    for (auto [v, w] : logic[u]) {
        int nc = c ^ w;
        if (color[v] == -1) {
            if (!dfs_color(v, nc)) return false;
        } else if (color[v] != nc) {
            return false; // mâu thuẫn logic
        }
    }
    return true;
}

// ========== Hàm powmod (2^k % MOD) ==========
long long modpow(long long a, long long b) {
    long long res = 1;
    while (b) {
        if (b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    depth[1] = 0;
    dfs_lca(1, 0);

    vector<pair<int,int>> pairs;
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        pairs.push_back({a, b});
        add_path(a, b);
    }

    connect(1, 0);

    // Nếu cần, thêm ràng buộc "ngược chiều" (parity = 1)
    // khi cả a và b khác LCA. (Không cần nếu chỉ xét đồng hướng)

    // ========== Tô màu đồ thị logic ==========
    long long ans = 1;
    memset(color, -1, sizeof(color));

    for (int i = 1; i <= n; i++) {
        if (color[i] == -1) {
            if (!dfs_color(i, 0)) {
                cout << 0 << "\n";
                return 0;
            }
            ans = (ans * 2) % MOD; // mỗi thành phần logic có 2 cách
        }
    }

    // ========== Đếm số cạnh tự do ==========
    int free_edges = 0;
    for (int u = 1; u <= n; u++) {
        for (int v : g[u]) if (v > u) { // tránh đếm 2 lần
            // cạnh (u,v) tự do nếu không nằm trong ràng buộc
            if (high[v] == 0 && high[u] == 0)
                free_edges++;
        }
    }

    ans = ans * modpow(2, free_edges) % MOD;

    cout << ans << "\n";
    return 0;
}
#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...
#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...