@Gary-Ying
2018-01-29T05:53:05.000000Z
字数 2100
阅读 1434
编程 解题报告
Description
求出这棵带边权的树的一条最大Xor路径
Input
第一行,一个整数N,表示一颗树有N个节点,接下来N-1行,每行三个整数a,b,c表示节点a和节点b之间有条权值为c的边(2<=n<=100000,1< a,b <=N,C<=2^31-1)
Output
输出仅一行,即所求的带边权树的Xor最大路径。样例输入
4
1 2 3
1 3 4
1 4 7
样例输出
7
使用1遍DFS遍历可以扫描出n个节点到root(根节点)的XOR路径,时间复杂度为 O(n);那么我们可以通过n遍DFS扫描出所有节点到所有其他节点的XOR路径,从而求得最大值。综合下来,时间复杂度为O(n^2)。妥妥超时~~~
我们来观察一下算法1,对于这个O(n^2)的算法,我们肯定不能去优化DFS的一层,也就是说,我们只能在枚举n个节点的一层下手,能不能只进行1遍DFS呢?答案是肯定的。
假设有这样1棵树:
6
1 2 a
2 3 b
3 4 c
4 5 d
1 6 e
我们用d[i]记录i节点到1节点的XOR距离,那么
d[3]=a xor b
d[5]=a xor c xor d
而3->5的XOR距离为 b xor c xor d = d[3] xor d[5]
于是我们得到 对于任意两点i,j(i<>j),i到j的XOR距离为 d[i] xor d[j] (d[i]记录i节点到1节点的XOR距离);
那么原题就转化为 在d[1..n]中,找出一对i,j(i<>j),使d[i] xor d[j]最大。如果用暴力枚举的方法,时间复杂度仍然是 O(n^2)。
看上去我们已经不知道如何优化了,不如举几个例子。
98=(1100010)B
43=(101011)B
98 XOR 43 = (1001001)B = 73
算法2中,枚举i是必不可少的,所以我们只能在j上下功夫,要优化j,只能、必须做到精确查找对于D[i]最优的j。
一遍AC!!!
varhead,d:array[0..100005] of longint;vet,val,next:array[0..200005] of longint;trie:array[0..3100005,0..2] of longint;edgenum,n,i,x,y,z,loc,ans,root,nodenum:longint;function max(a,b:longint):longint;beginif a>b then exit(a);exit(b);end;procedure addedge(u,v,cost:longint);begininc(edgenum);vet[edgenum]:=v;val[edgenum]:=cost;next[edgenum]:=head[u];head[u]:=edgenum;end;procedure dfs(u,fa:longint);vare,v,cost:longint;begine:=head[u];while e<>0 dobeginv:=vet[e];cost:=val[e];if v<>fa thenbegind[v]:=d[u] xor cost;dfs(v,u);end;e:=next[e];end;end;procedure ins(root,val,id:longint);varnow,son,i:longint;beginnow:=root;for i:=30 downto 0 dobeginson:=val shr i and 1;if trie[now,son]=0 thenbegininc(nodenum);trie[now,son]:=nodenum;end;now:=trie[now,son];end;trie[now,2]:=id;end;function find_trie(root,key:longint):longint;var now,son,i:longint;beginnow:=root;for i:=30 downto 0 dobeginson:=key shr i and 1;if trie[now,son xor 1]<>0 then now:=trie[now,son xor 1]else now:=trie[now,son];end;exit(trie[now,2]);end;beginreadln(n);edgenum:=0;for i:=1 to n-1 dobeginreadln(x,y,z);addedge(x,y,z);addedge(y,x,z);end;dfs(1,-1);root:=1; nodenum:=1;for i:=1 to n doins(root,d[i],i);ans:=d[1] xor d[2];for i:=1 to n dobeginloc:=find_trie(root,d[i]);ans:=max(ans,d[i] xor d[loc]);end;writeln(ans);end.