POJ 3764 The xor-longest Path(字典树 + 贪心)
2015-08-17 22:03
531 查看
题目链接:http://poj.org/problem?id=3764
题意:给出一棵N个点的树,定义两点间的异或权值为这两点间的所有边权的异或值,求树中最大的两点异或权值
思路:对于异或有性质 A ^ C = (A ^ B) ^ (B ^ C),故而树上两点A, C的异或值可以通过与两点分别于根节点的异或值再异或得到,这样可以先预处理出所有点到根节点的异或值,然后考虑这N个值如何选出两个值异或值最大,可以将每个值从高位到低位拆成二进制的串插入字典树,每当插入完成后就在字典树上进行遍历,因为是从高位到低位,所以每次应保证高位的值尽量能取到,所以每次尽量找与当前位相反的结点进行遍历
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#include <deque>
#include <ctime>
#include <string>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn = 100010;
const int maxm = 6000010;
int cnt, head[maxn], dis[maxn];
struct Edge
{
int to, w, next;
} edge[maxn << 1];
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w)
{
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u, int fa, int w)
{
dis[u] = w;
for (int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if (v == fa) continue;
dfs(v, u, w ^ edge[i].w);
}
}
struct Trie
{
int ch[maxm][2];
int sz;
void init()
{
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
void insert(int num)
{
int u = 0;
for (int i = 30; i >= 0; i--)
{
int w;
if (num & (1 << i))
w = 1;
else
w = 0;
if (!ch[u][w])
{
memset(ch[sz], 0, sizeof(ch[sz]));
ch[u][w] = sz++;
}
u = ch[u][w];
}
}
int query(int num)
{
int u = 0, res = 0;
for (int i = 30; i >= 0; i--)
{
int w;
if (num & (1 << i))
w = 1;
else
w = 0;
if (ch[u][w ^ 1])
{
u = ch[u][w ^ 1];
res *= 2;
res += 1;
}
else
{
u = ch[u][w];
res *= 2;
}
}
return res;
}
} tr;
int main()
{
int n;
while (~scanf("%d", &n))
{
init();
for (int i = 0; i < n - 1; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}
dfs(0, -1, 0);
// for (int i = 0; i < n; i++)
// printf("%d ", dis[i]);
tr.init();
int ans = 0;
for (int i = 0; i < n; i++)
{
tr.insert(dis[i]);
ans = max(ans, tr.query(dis[i]));
}
cout << ans << endl;
}
return 0;
}
题意:给出一棵N个点的树,定义两点间的异或权值为这两点间的所有边权的异或值,求树中最大的两点异或权值
思路:对于异或有性质 A ^ C = (A ^ B) ^ (B ^ C),故而树上两点A, C的异或值可以通过与两点分别于根节点的异或值再异或得到,这样可以先预处理出所有点到根节点的异或值,然后考虑这N个值如何选出两个值异或值最大,可以将每个值从高位到低位拆成二进制的串插入字典树,每当插入完成后就在字典树上进行遍历,因为是从高位到低位,所以每次应保证高位的值尽量能取到,所以每次尽量找与当前位相反的结点进行遍历
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#include <deque>
#include <ctime>
#include <string>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn = 100010;
const int maxm = 6000010;
int cnt, head[maxn], dis[maxn];
struct Edge
{
int to, w, next;
} edge[maxn << 1];
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w)
{
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u, int fa, int w)
{
dis[u] = w;
for (int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if (v == fa) continue;
dfs(v, u, w ^ edge[i].w);
}
}
struct Trie
{
int ch[maxm][2];
int sz;
void init()
{
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
void insert(int num)
{
int u = 0;
for (int i = 30; i >= 0; i--)
{
int w;
if (num & (1 << i))
w = 1;
else
w = 0;
if (!ch[u][w])
{
memset(ch[sz], 0, sizeof(ch[sz]));
ch[u][w] = sz++;
}
u = ch[u][w];
}
}
int query(int num)
{
int u = 0, res = 0;
for (int i = 30; i >= 0; i--)
{
int w;
if (num & (1 << i))
w = 1;
else
w = 0;
if (ch[u][w ^ 1])
{
u = ch[u][w ^ 1];
res *= 2;
res += 1;
}
else
{
u = ch[u][w];
res *= 2;
}
}
return res;
}
} tr;
int main()
{
int n;
while (~scanf("%d", &n))
{
init();
for (int i = 0; i < n - 1; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}
dfs(0, -1, 0);
// for (int i = 0; i < n; i++)
// printf("%d ", dis[i]);
tr.init();
int ans = 0;
for (int i = 0; i < n; i++)
{
tr.insert(dis[i]);
ans = max(ans, tr.query(dis[i]));
}
cout << ans << endl;
}
return 0;
}
相关文章推荐
- Kruskal算法-图由邻接表实现
- 编辑距离计算-动态规划法
- 在Unity项目中使用渐进网格技术
- NS3网络仿真(12): ICMPv4协议
- java中String的常用方法
- Shell脚本学习笔记
- hdu(1069)——Monkey and Banana(LIS变形)
- POJ 3080--Blue Jeans【KMP && 暴力枚举】
- 每日五题(mybatis)
- Linux 网卡驱动学习(七)(MAC 与 IP)
- hdu1010Tempter of the Bone(dfs+奇偶剪枝)
- [笔记][Java7并发编程实战手册]3.3 资源的多副本并发访问控制Semaphore
- HDU 3790 最短路径问题【最短路 dijkstra 双权值】
- php使用curl post 乱码 淘宝手机 curl 注意事项 cookie无法传递
- Redis与SpringMVC整合
- 继承中的构造方法
- Python with MySql in Ubuntu
- zedboard 开启rz sz串口命令支持
- 编程一开始就应该养成的好习惯
- Visible Lattice Points(spoj7001+初探莫比乌斯)gcd(a,b,c)=1 经典