A国拥有n个城市,其交通系统呈树状结构,即任意两个城市存在且仅存在一条路径将其连接。B国是A国的敌国企图秘密发射导弹打击A国,由于情报有限A国的特工们并不知道有哪几座城市会被打击。一座城市被炸毁后,与其相连的交通线也将损毁。现假设每座城市都有50%的概率被炸毁,问B国发动袭击后A国期望有多少对城市仍连通。
样例解释:
城市{1,2,3}被炸毁:没有城市连通
城市{1,2}被炸毁:没有城市连通
城市{1,3}被炸毁:没有城市连通
城市{2,3}被炸毁:没有城市连通
城市1被炸毁:城市{2,3}连通
城市2被炸毁:没有城市连通
城市3被炸毁:城市{1,2}连通
没有城市被炸毁:城市{1,2}、{2,3}、{1,3}连通
Input
一个数n(2<=n<=100000)
接下来n-1行,每行两个数x,y表示一条交通线。(1<=x,y<=n)
数据保证其交通系统构成一棵树。
Output
一个数,表示答案乘2^n后对1,000,000,007取模后的值。
Input示例
3
1 2
2 3
Output示例
5
思路:
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
const int MOD = 1e9 + 7;
int n;
int tot;
int head[MAXN];
ll ans[MAXN];
ll sum[MAXN];
ll siz[MAXN];
ll pow_2[MAXN];
struct Edge
{
int to, prev;
};
Edge edges[MAXN << 1];
void addEdge(int u, int v)
{
++tot;
edges[tot].to = v;
edges[tot].prev = head[u];
head[u] = tot;
}
void dfs(int cur, int father)
{
sum[cur] = siz[cur] = 1LL;
ans[cur] = 0LL;
for (int i = head[cur]; i; i = edges[i].prev)
{
int peer = edges[i].to;
if (peer != father)
{
dfs(peer, cur);
ans[cur] = ((ans[cur] * pow_2[siz[peer]]) % MOD
+ (ans[peer] * pow_2[siz[cur]]) % MOD
+ sum[cur] * sum[peer] % MOD) % MOD;
sum[cur] = (sum[cur] * pow_2[siz[peer]] % MOD
+ sum[peer] * pow_2[siz[cur] - 1] % MOD) % MOD;
siz[cur] = (siz[cur] + siz[peer]) % MOD;
}
}
}
void init()
{
pow_2[0] = 1;
for (int i = 1; i < MAXN; i++)
{
pow_2[i] = (pow_2[i - 1] << 1) % MOD;
}
}
template <class T>
inline void scan_d(T &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0'), c = getchar();
}
}
int main()
{
init();
scan_d(n);
int x, y;
for (int i = 1; i < n; i++)
{
scan_d(x);
scan_d(y);
addEdge(x, y);
addEdge(y, x);
}
dfs(1, 0);
printf("%lld\n", ans[1]);
return 0;
}