51Nod-1322-关于树的函数
2017-04-28 23:13
218 查看
ACM模版
暂且不说树归部分,我们先考虑任何一种状态下如何求 S(e1,e2)2。其实这里我们并不需要直接算出 A1、A2、B1、B2,只需要根据部分数据就能推出其他数据。
假如 A1 集合中有 n 个结点,那么 A2 集合中有 N - n 个结点。假如 B1 集合中有 m 个结点,那么 B2 集合中有 N-m 个结点。
假如 A1 与 B1 交集有 cnt 个结点,那么 A1 与 B2 交集有 n-cnt 个结点,那么 A2 与 B1 交集有 m-cnt 个结点,那么 A2 与 B2 交集有 N-m-n+cnt 个结点。
假如……那么……没了,这个部分就这样!
接着就是树归部分,如何枚举出所有情况?首先我们可以对 Tree1 的一个子树进行 dfs(),标记为集合 A1,然后在这个状态下对 Tree2 进行 dfs_(),这个部分就切切实实是树归了,在回溯的过程中进行上述规则的计数累加即可。
具体的还是要分析代码,理解了树归也就不难看懂代码了。
这里利用了 tuple 容器,如果不用这个容器就需要用到结构体指针了,毕竟 dfs_() 过程中要返回两个值,分别是 cnt 和 m。
描述
题解
典型的树归问题,复杂度 O(n2)。暂且不说树归部分,我们先考虑任何一种状态下如何求 S(e1,e2)2。其实这里我们并不需要直接算出 A1、A2、B1、B2,只需要根据部分数据就能推出其他数据。
假如 A1 集合中有 n 个结点,那么 A2 集合中有 N - n 个结点。假如 B1 集合中有 m 个结点,那么 B2 集合中有 N-m 个结点。
假如 A1 与 B1 交集有 cnt 个结点,那么 A1 与 B2 交集有 n-cnt 个结点,那么 A2 与 B1 交集有 m-cnt 个结点,那么 A2 与 B2 交集有 N-m-n+cnt 个结点。
假如……那么……没了,这个部分就这样!
接着就是树归部分,如何枚举出所有情况?首先我们可以对 Tree1 的一个子树进行 dfs(),标记为集合 A1,然后在这个状态下对 Tree2 进行 dfs_(),这个部分就切切实实是树归了,在回溯的过程中进行上述规则的计数累加即可。
具体的还是要分析代码,理解了树归也就不难看懂代码了。
这里利用了 tuple 容器,如果不用这个容器就需要用到结构体指针了,毕竟 dfs_() 过程中要返回两个值,分别是 cnt 和 m。
代码
#include <iostream> #include <algorithm> #include <cstring> #include <vector> #include <set> #include <tuple> using namespace std; typedef long long ll; typedef tuple<int, int> tii; const int MAXN = 4e3 + 10; int N; int n; // A1集合结点数 ll res = 0; vector<int> tree[MAXN]; vector<int> tree_[MAXN]; tii tmp; struct edge { int u; int v; } tr[MAXN], tr_[MAXN]; int vis[MAXN]; tii dfs_(int last, int root) { int cnt = 0, m = 0; if (vis[root]) { cnt++; } m++; int a, b; for (int i = 0; i < tree_[root].size(); i++) { if (tree_[root][i] != last) { tmp = dfs_(root, tree_[root][i]); tie(a, b) = tmp; cnt += a; m += b; } } if (m == N) { return make_tuple(cnt, m); } long long maxRes = 0; maxRes = max(maxRes, (ll)cnt * cnt); maxRes = max(maxRes, (ll)(n - cnt) * (n - cnt)); maxRes = max(maxRes, (ll)(m - cnt) * (m - cnt)); maxRes = max(maxRes, (ll)(N - m - n + cnt) * (N - m - n + cnt)); res += maxRes; return make_tuple(cnt, m); } void dfs(int last, int root) { vis[root] = 1; n++; for (int i = 0; i < tree[root].size(); i++) { if (tree[root][i] != last) { dfs(root, tree[root][i]); } } } int main(int argc, const char * argv[]) { // freopen("/Users/zyj/Desktop/input.txt", "r", stdin); cin >> N; int u, v; for (int i = 1; i < N; i++) { scanf("%d%d", &u, &v); u++, v++; tree[u].push_back(v); tree[v].push_back(u); tr[i].u = u; tr[i].v = v; } for (int i = 1; i < N; i++) { scanf("%d%d", &u, &v); u++, v++; tree_[u].push_back(v); tree_[v].push_back(u); tr_[i].u = u; tr_[i].v = v; } for (int i = 1; i < N; i++) { n = 0; memset(vis, 0, sizeof(vis)); dfs(tr[i].v, tr[i].u); dfs_(-1, 1); } cout << res << '\n'; return 0; }
相关文章推荐
- 关于函数和字符指针的一些看法。
- 关于字符串的几个有用函数
- 网友收藏的一些关于VB处理的函数
- 关于ATL自动生成的事件激发函数Fire_XXX(...)的代码说明
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- Delphi6函数大全之SysUtils.pas(关于字符串格式)
- 关于document.execCommand()函数可用参数大解析
- 关于C++中的虚函数
- 关于document.execCommand()函数可用参数大解析
- 关于datawindow控件,GetChild()函数的一点经验
- 刚才遇到了关于C#使用外部DLL函数上的char*的问题。
- sql server 关于函数中如何使用Getdate() (转贴)
- 关于时间函数
- 关于VC中的时间函数讨论
- Js:关于document.execCommand()函数可用参数大解析
- PHP 小技巧之(5)关于PHP中var_dump()函数的概念、用途。
- 关于日期天数计算的几个函数!
- 关于rownum排序分页会比分析函数排序快的问题。。。
- 关于函数返回的局部数组的问题
- 『EXP2』关于在函数内部分配内存时需要注意的问题