HDU 4705 Y 多校训练第十场1010
2013-10-12 14:30
465 查看
题意就是在一棵树上找三个点,使得没有一条简单路径包含这三个点。
我们换个角度来想,所有方案很好求,n个里选3个的组合数, 然后我们减去在一条简单路径上的三点对的个数。于是问题转化成求这样的三点对,我是这么想的,可以枚举2个点, 把不符合要求的第三个点找到,然后因为树上的两点有唯一的简单路径相连, 于是我们就可以知道有多少个点是不能作为第三个点的点了。个数恰好等于两端这两个点之间的距离减1。(每条边权值为1,因此这个答案应该很好理解,假设简单路径是 A,X,Y,Z,B,距离4,有三个点不能作为C)。于是我们就把问题转化成求任意两个节点之间的距离了,也就是以一个节点为根,其他节点到他的距离之和,这样问题基本解决,显然树DP,我们考虑一下转移过程需要的信息,假设已经知道某个节点A,以他为根时其他节点到他的距离之和,那么DFS转移到他的子节B点时,我们会发现有些点距离加了1,有些点距离减了1,加一的点是除了B及B的子树以外的节点,而减一的是B的子树上的点,于是我们需要每个节点的子树节点数目的信息。其他信息可以不要,当然可以开一个数组记录以每个节点为根的时候的距离和,但是没有必要,我们直接把他加到答案dis上去就可以了。所以树DP就这样进行下去:先找一个节点,做一遍DFS,知道了他到所有其他节点的距离之和,这个有用,同时我们保存每个节点的子树的节点数信息。然后开始第二遍DFS,考虑距离和这个量如何转移:A的dis和为sum,他的子节点B的子树有s[B]个节点(包括本身),那么
n - s[B] 个点距离加1,B的子树上的点距离减1,s[B](注意B原来对A贡献了1,现在不贡献所以B也算在减一的节点里面),于是以B为根的树的距离和就是 sum + n - s[B] * 2, 最后还有一些小细节,就是我们求的是距离之和,没有减1,应该减多少个1呢?我们对每个点都让他做了一次根节点,其他作为他的子节点有n - 1个所以应该减去(n - 1) * n,最后我们注意到我们重复计算了答案,因为路径A--B 与B--A是一样的,所以答案除以2。到此这题解决。
表示我是弱菜,以前根本不会树DP,这是A的第一题,希望不要鄙视,还有数的存储用的是数组模拟的领接表,以前也不会,队友教的,所以把这个学了好多东西的题写篇blog记录下来!
代码:
我们换个角度来想,所有方案很好求,n个里选3个的组合数, 然后我们减去在一条简单路径上的三点对的个数。于是问题转化成求这样的三点对,我是这么想的,可以枚举2个点, 把不符合要求的第三个点找到,然后因为树上的两点有唯一的简单路径相连, 于是我们就可以知道有多少个点是不能作为第三个点的点了。个数恰好等于两端这两个点之间的距离减1。(每条边权值为1,因此这个答案应该很好理解,假设简单路径是 A,X,Y,Z,B,距离4,有三个点不能作为C)。于是我们就把问题转化成求任意两个节点之间的距离了,也就是以一个节点为根,其他节点到他的距离之和,这样问题基本解决,显然树DP,我们考虑一下转移过程需要的信息,假设已经知道某个节点A,以他为根时其他节点到他的距离之和,那么DFS转移到他的子节B点时,我们会发现有些点距离加了1,有些点距离减了1,加一的点是除了B及B的子树以外的节点,而减一的是B的子树上的点,于是我们需要每个节点的子树节点数目的信息。其他信息可以不要,当然可以开一个数组记录以每个节点为根的时候的距离和,但是没有必要,我们直接把他加到答案dis上去就可以了。所以树DP就这样进行下去:先找一个节点,做一遍DFS,知道了他到所有其他节点的距离之和,这个有用,同时我们保存每个节点的子树的节点数信息。然后开始第二遍DFS,考虑距离和这个量如何转移:A的dis和为sum,他的子节点B的子树有s[B]个节点(包括本身),那么
n - s[B] 个点距离加1,B的子树上的点距离减1,s[B](注意B原来对A贡献了1,现在不贡献所以B也算在减一的节点里面),于是以B为根的树的距离和就是 sum + n - s[B] * 2, 最后还有一些小细节,就是我们求的是距离之和,没有减1,应该减多少个1呢?我们对每个点都让他做了一次根节点,其他作为他的子节点有n - 1个所以应该减去(n - 1) * n,最后我们注意到我们重复计算了答案,因为路径A--B 与B--A是一样的,所以答案除以2。到此这题解决。
表示我是弱菜,以前根本不会树DP,这是A的第一题,希望不要鄙视,还有数的存储用的是数组模拟的领接表,以前也不会,队友教的,所以把这个学了好多东西的题写篇blog记录下来!
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<queue> #include<algorithm> #include<stack> #include<deque> #include<list> #include<set> #include<vector> #include<iomanip> #include<cctype> #include<string> #include<memory> #include<map> #include<sstream> #pragma warning (disable : 4996) #define mem(a) memset(a, 0, sizeof(a)) #define sl(a) strlen(a) #define LL long long #define dou double const LL Mod = 1000000007; const LL N = 100005; using namespace std; LL f , e[2 * N], ne[2 * N], s , dis, ans, tot, n; void add(LL x, LL y){ ne[++tot] = f[x], f[x] = tot, e[tot] = y; } void dfs(LL x, LL p, LL dep){ dis += dep; for (LL i = f[x]; i; i = ne[i]){ if (e[i] != p){ dfs(e[i], x, dep + 1); s[x] += s[e[i]]; } } } void dfs2(LL x, LL p, LL sum){ //cout << x << ' ' << sum << endl; ans += sum; for (LL i = f[x]; i; i = ne[i]){ if (e[i] != p){ dfs2(e[i], x, sum + n - 2 * s[e[i]]); } } } void init(){ mem(f), mem(ne), mem(e); for (LL i = 1; i <= N ;++i) s[i] = 1; dis = tot = ans = 0; } int main() { /*freopen("in.txt", "r", stdin); freopen("out.txt", "w",stdout);*/ //LL size = 256 << 20; // 256MB // char *p = (char*) malloc(size) + size; // __asm__("movl %0, %%esp\n" :: "r"(p)); ios :: sync_with_stdio(false); LL x, y; while (cin >> n){ init(); for (LL i = 0; i < n - 1; ++i){ cin >> x >> y; add(x, y), add(y, x); } dfs(1, -1, 0); //cout << dis << endl; //for (LL i = 1; i <= n; ++i) cout << i << ' ' << s[i] << endl; dfs2(1, -1, dis); ans = ans - n * (n - 1); cout << (n - 1) * (n - 2) * n / 6 - (ans / 2) << endl; } return 0; }
相关文章推荐
- HDU 4920(杭电多校训练#5 1010 题) Matrix multiplication(不知道该挂个什么帽子。。。)
- 2017 第十场多校训练 HDU 6181 Two Paths 次短路+Dijkstra
- HDU-2017 多校训练赛10-1010-Schedule
- hdu 4705 Y 多校第十场
- 2017 多校训练第十场 HDU 6178 Monkeys 最小点覆盖+树形DP
- hdu 4705 Y/杭电2013年多校第十场1010 组合
- hdu 4901 The Romantic Hero(计数dp)2014多校训练第4场1005
- HDU 5818 多校第七场 1010 Joint Stacks (线段树)
- hdu 4617 2013多校联合训练第二场weapon简单的计算几何
- 【多校训练】hdu 6066 RXD's date
- HDU-2017 多校训练赛9-1010-Two strings
- 多校联合训练8&&HDU 5828
- hdu 6181 Two Paths (多校第十场)
- hdu4699 Editor 2013 多校训练第十场 D题 数列维护 splay | 线段树 | 栈!!!!!
- HDU 2017 多校联合训练赛6 1010 6105 Gameia
- hdu 4930 Fighting the Landlords(多校6 1010)
- HDU-2017 多校训练赛10-1008-Monkeys
- HDU-2017 多校训练赛10-1002-Array Challenge
- hdu 4632 Palindrome subsequence 区间dp 多校联合训练第四场
- hdu 4923 Room and Moor(数学题)2014多校训练第6场