当前位置: 代码迷 >> 综合 >> 树型dp hdu5647 DZY Loves Connecting
  详细解决方案

树型dp hdu5647 DZY Loves Connecting

热度:34   发布时间:2023-12-14 03:19:10.0

传送门:点击打开链接

题意:定义连通集S为,任意一对u,v属于S,u到v的树最短路径经过所有的节点都在S内。求所有这样的连通集大小之和

思路:看到维护大小之和,通常还需要维护数量。

看了下吉司机的代码写的很简单,只要理解好乘法原理,就很好做了

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <Stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout << "[" << x << "]"
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w+", stdout)
//#pragma comment(linker, "/STACK:102400000,102400000") 
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;const int MX = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;struct Edge {int v, nxt;
} E[MX << 1];
int Head[MX], erear;
void edge_init() {erear = 0;memset(Head, -1, sizeof(Head));
}
void edge_add(int u, int v) {E[erear].v = v;E[erear].nxt = Head[u];Head[u] = erear++;
}LL A[MX], B[MX];
void DFS(int u, int f) {A[u] = B[u] = 1;for(int i = Head[u]; ~i; i = E[i].nxt) {int v = E[i].v; if(v == f) continue;DFS(v, u);B[u] = (B[u] * (A[v] + 1) + A[u] * B[v]) % mod;A[u] = A[u] * (A[v] + 1) % mod;}
}int main() {int T, n; //FIN;scanf("%d", &T);while(T--) {scanf("%d", &n);edge_init();for(int u = 2; u <= n; u++) {int v; scanf("%d", &v);edge_add(u, v);edge_add(v, u);}DFS(1, -1);LL ans = 0;for(int i = 1; i <= n; i++) {ans = (ans + B[i]) % mod;}printf("%I64d\n", ans);}return 0;
}