傳送門php
首先,全部連通塊的個數的指望再減去每一個點孤立的機率就是答案。
設 \(d_i\) 表示 \(i\) 的度數,那麼每一個點孤立的機率爲 \(\frac{1}{2^{d_i}}\)
考慮計算全部連通塊的個數的指望
對於一棵樹來講,每次刪除一條邊會使得連通塊的個數 \(+1\),機率爲 \(\frac{1}{2}\),那麼 \(n-1\) 條邊的指望就是 \(1+\frac{n-1}{2}\)
對於仙人掌來講,若是此次刪的是環上第一個被刪除的邊,那麼不會貢獻答案,因此要減去在一個環上至少刪除了一條邊的機率,設長度爲 \(len\),就要減去 \(1-\frac{1}{2^{len}}\)
因此只要求出每一個環就行了。c++
# include <bits/stdc++.h> using namespace std; typedef long long ll; namespace IO { const int maxn(1 << 21 | 1); char ibuf[maxn], *iS, *iT, c; int f; inline char Getc() { return (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, maxn, stdin), (iS == iT ? EOF : *iS++)) : *iS++); } template <class Int> inline void In(Int &x) { for (f = 1, c = Getc(); c < '0' || c > '9'; c = Getc()) f = c == '-' ? -1 : 1; for (x = 0; c <= '9' && c >= '0'; c = Getc()) x = (x << 3) + (x << 1) + (c ^ 48); x *= f; } } using IO :: In; const int maxn(1e6 + 5); const int mod(1e9 + 7); inline void Inc(int &x, const int y) { x = x + y >= mod ? x + y - mod : x + y; } inline void Dec(int &x, const int y) { x = x - y < 0 ? x - y + mod : x - y; } inline int Add(int x, const int y) { return x + y >= mod ? x + y - mod : x + y; } inline int Sub(int x, const int y) { return x - y < 0 ? x - y + mod : x - y; } inline int Pow(ll x, int y) { ll ret = 1; for (; y; y >>= 1, x = x * x % mod) if (y & 1) ret = ret * x % mod; return ret; } struct Edge { int to, next; }; int n, m, d[maxn], first[maxn], cnt, inv2[maxn << 1], fa[maxn], ans, vis[maxn], deep[maxn]; Edge edge[maxn << 2]; inline void AddEdge(int u, int v) { edge[cnt] = (Edge){v, first[u]}, first[u] = cnt++, ++d[u]; edge[cnt] = (Edge){u, first[v]}, first[v] = cnt++, ++d[v]; } void Dfs(int u, int ff) { int e, v, len, cur; vis[u] = 1; for (e = first[u]; ~e; e = edge[e].next) if ((v = edge[e].to) ^ ff) { if (!vis[v]) deep[v] = deep[u] + 1, fa[v] = u, Dfs(v, u); else if (deep[v] < deep[u]) { for (len = 1, cur = u; cur ^ v; cur = fa[cur]) ++len; Dec(ans, (ll)Sub(1, inv2[len]) % mod); } } } int main() { int i, u, v; memset(first, -1, sizeof(first)); In(n), In(m); inv2[0] = 1, inv2[1] = (mod + 1) >> 1; for (v = m + m, i = 2; i <= v; ++i) inv2[i] = (ll)inv2[i - 1] * inv2[1] % mod; for (i = 1; i <= m; ++i) In(u), In(v), AddEdge(u, v); ans = Add(1, (ll)m * inv2[1] % mod), Dfs(1, 0); for (i = 1; i <= n; ++i) Dec(ans, inv2[d[i]]); ans = (ll)ans * Pow(2, m) % mod, printf("%d\n", ans); return 0; }