您的位置:首页 > 产品设计 > UI/UE

2016 UESTC Training for Data Structures L - 郭大侠与苦恼 CDOJ 1284 map+启发式合并

2016-05-01 14:35 459 查看
L -
郭大侠与苦恼
题目简单,就是给你一棵树,然后问异或值为0的简单路径有多少条
好难,好麻烦,想了好久才想明白
按dfs的顺序来map+启发式合并,
后来想找个题的大概框架和树形01背包相似,都是用dfs来实现的,只不过树形01背包dfs后的过程是背包的合并,这个是map的合并,还是启发式合并(就是把size小的合并到size大的上),
然后我们这里维护的是pre[u],就是从根节点到u的简单路径异或和,
u到v的简单路径异或和就是pre[u]^pre[v]^lca(u,v)
对于一个dfs,根节点的map维护之前遍历过的子树的每个异或值的个数,然后当前的儿子节点继续往下dfs,在回溯到这里的时候,这个节点上的map就已经维护好了以它为根的各个异或值的个数,然后我们就统计就好了,选择一个size小的进行遍历,对于每个值x,查询x^now(now代表当前的这个根节点,就是他们的最近公共祖先)在另一个map中出现的次数,然后查询完了之后,合并,如果根节点的size比儿子节点的size大,就先交换一下,再合并,就好了
总之就是dfs的框架思路和树形01背包的框架思路是一样的,我感觉,就是在dfs的的过程中维护它就好,维护一个之前已经遍历完的,和这个节点dfs之后回溯回来的,把这两个合并到一起就行

代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define ll long long
#define maxn 100005
int n, idx[maxn];
bool vis[maxn];
vector<int> tree[maxn];
map<int, int> XOR[maxn];//记录以该节点为根的子树的各个异或值的计数
ll ans = 0;
void dfs_print(int now)
{
vis[now] = 1;
for (int i = 0; i < tree[now].size(); ++i)
{
if (vis[tree[now][i]])
continue;
printf("%d %d\n", now, tree[now][i]);
dfs_print(tree[now][i]);
}
}
void dfs(int now, int value)
{
vis[now] = 1;
++XOR[now][value];
//printf("every %d %d\n", now, value);
for (int i = 0; i < tree[now].size(); ++i)
{
int tmp = tree[now][i];
if (!vis[tmp])
{
dfs(tmp, value^tmp);
if (XOR[now].size() < XOR[tmp].size())//统计当前子树和根节点及之前所有子树异或值相同的个数
{
for (map<int, int>::iterator itor = XOR[now].begin(); itor != XOR[now].end(); ++itor)
{
if (XOR[tmp].find(now ^ (itor->first)) != XOR[tmp].end())
ans += (itor->second)*XOR[tmp][now ^ (itor->first)];
}
XOR[now].swap(XOR[tmp]);
}
else
{
for (map<int, int>::iterator itor = XOR[tmp].begin(); itor != XOR[tmp].end(); ++itor)
{
if (XOR[now].find(now ^ (itor->first)) != XOR[now].end())
ans += (itor->second)*XOR[now][now ^ (itor->first)];
}
}
//把子树并入到它的父节点中
for (map<int, int>::iterator itor = XOR[tmp].begin(); itor != XOR[tmp].end(); ++itor)
{
XOR[now][itor->first] += itor->second;
}
/*for (map<int, int>::iterator itor = XOR[now].begin(); itor != XOR[now].end(); ++itor)
printf("%d %d\n", itor->first, itor->second);
printf("%d %d  ans %lld\n", now, tmp, ans);*/
}
}
}
int main()
{
//freopen("input.txt", "r", stdin);
scanf("%d", &n);
int u, v;
for (int i = 0; i < n - 1; ++i)
{
scanf("%d%d", &u, &v);
tree[u].push_back(v);
tree[v].push_back(u);
}
/*dfs_print(1);
printf("ssssssssssss\n");
memset(vis, 0, sizeof(vis));*/
dfs(1, 1);
printf("%lld\n", ans);
//system("pause");
//while (1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: