题目链接:https://www.luogu.com.cn/problem/P4551
题意:给定n个点(1<=n<=1e5),n-1条带权无向边 u,v,w。求最大的异或路径,即所有最短路径中的异或和的最大值。
题解:01Trie模板题
1.求num[i]:首先在原树上随便选择一个点作为根节点s,然后num[i]表示表示根节点到点i的路径异或和,那么任意两点j,k之间的路径异或和为num[j]^num[k]。
2.利用num[i]建立二进制Trie树:优化空间,空间复杂度降到大概O(n*30)。
3.求最大路径异或和:ans=max(ans,query(num[i]))。query返回的是num[i]与某一个num[j]的最大值,一次查询时间复杂度大概只需要O(30)。具体操作见代码
总结:这题是很模板的01Trie,提供了新的解题思路。
算法学习重深度还是广度。我的选择是:能深度尽量深度,疲惫之后就广度,把字符串的只是全部联结起来,然后不断突破自己即可。
好好总结一下模板!
代码:
#include <bits/stdc++.h>
#define ll long long
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x,y) make_pair(x,y)
#define rep(i,a,n) for(ll i=a;i<=n;i++)
#define per(i,n,a) for(ll i=n;i>=a;i--)
#define dbg(x) cout << #x << "===" << x << endl
#define dbgg(l,r,x) for(ll i=l;i<=r;i++) cout<<x[i]<<" ";cout<<"<<<"<<#x;cout<<endl
using namespace std;
template<class T>void read(T &x){T res=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){res=(res<<3)+(res<<1)+c-'0';c=getchar();}x=res*f;}
void print(ll x){if(x<0){putchar('-');x=-x;}if(x>9)print(x/10);putchar(x%10+'0');}
const ll maxn = 1e5 + 10;
const ll mod = 1e9+7;
ll n,u,v,w;
ll num[maxn];
struct Trie_01{
ll trie[maxn*30][2],val[maxn*30],cnt;//注意cnt的最大值
vector<pll > g[maxn];
//01Trie插入数
void insert(ll s){
ll u=0;
for(ll i=30;i>=0;i--){
ll t=1<<i;//dbg(t),标记一下,检查是否溢出;
bool x=s&t;//注意应是bool型,不然x=0/t,而非0/1
if(!trie[u][x]) trie[u][x]=++cnt;
u=trie[u][x];
}
val[u]=1;
}
//返回与s异或得到的最大值
ll query(ll s){
ll res=0,u=0;
for(ll i=30;i>=0;i--){
ll t=1<<i;//dbg(t);
bool x=s&t;
// cout<<">>>"<<i<<" "<<x<<endl;
if(trie[u][!x]) res+=t,u=trie[u][!x];
else u=trie[u][x];
}
return res;
}
//最开始给的是一颗带权无向边树,dfs求num[i]
void dfs(ll x,ll fa){
for(auto i:g[x]){
if(i.fi==fa) continue;
num[i.fi]=i.se^num[x];//?num[i]表示根节点到i点的路径异或和
dfs(i.fi,x);
}
}
}T;
int main() {
ll _s = 1;
// read(_s);
//freopen("testdata.in","r",stdin);
//freopen("testout.out","w",stdout);
for (ll _=1;_<=_s;_++) {
read(n);
rep(i,1,n-1){
read(u),read(v),read(w);
T.g[u].pb(mp(v,w));
T.g[v].pb(mp(u,w));
}
T.dfs(1,-1);
// dbgg(1,n,num);
rep(i,1,n) T.insert(num[i]);
ll ans=0;
rep(i,1,n) ans=max(ans,T.query(num[i]));
cout<<ans<<endl;
}
return 0;
}