题解:P16445 [XJTUPC 2026] The Whole Rest
lizihan250 · · 题解
如果对各类技巧熟悉的话应该可以轻松通过的一道题目。
首先注意到,从树上任意一点出发并回到自身的途径的边权异或和总是
注意到在这样一条路径中,把仅经过一次的路径拿出来必然是一条链,则我们希望这条链的边权异或和为
一种做法是,借鉴树的直径的 DFS 求法:任选一个点
::::success[参考实现]
#include<bits/stdc++.h>
using namespace std;
const int Maxn=500000,Maxw=20;
int n,m=-1,lg[Maxn+10];
vector<vector<pair<int,int> > > adj;
map<int,int> mp;
vector<vector<int> > p;
pair<int,int> res={1,1};
int maxd=0;
vector<int> ans;
struct node
{
int dep,val,nxt,fa[Maxw+2];
}nums[Maxn+10];
void dfs(int u,int fa)
{
if(mp.find(nums[u].val)==mp.end()) m++,mp[nums[u].val]=m,p.push_back({u});
else p[mp[nums[u].val]].push_back(u);
for(int i=1;i<=lg[nums[u].dep];i++)
nums[u].fa[i]=nums[nums[u].fa[i-1]].fa[i-1];
for(pair<int,int> v:adj[u])
{
if(v.first==fa) continue;
nums[v.first].dep=nums[u].dep+1;
nums[v.first].val=nums[u].val^v.second;
nums[v.first].fa[0]=u;
dfs(v.first,u);
}
return;
}
int lca(int u,int v)
{
if(nums[u].dep>nums[v].dep) swap(u,v);
while(nums[v].dep>nums[u].dep)
v=nums[v].fa[lg[nums[v].dep-nums[u].dep]];
if(u==v) return u;
for(int i=lg[nums[u].dep];i>=0;i--)
if(i<=lg[nums[u].dep]&&nums[u].fa[i]!=nums[v].fa[i]) u=nums[u].fa[i],v=nums[v].fa[i];
return nums[u].fa[0];
}
int dis(int u,int v){return nums[u].dep+nums[v].dep-(nums[lca(u,v)].dep<<1);}
void tag(int u,int v)
{
int l=lca(u,v);
while(u!=l)
nums[u].nxt=nums[u].fa[0],u=nums[u].fa[0];
while(v!=l)
nums[nums[v].fa[0]].nxt=v,v=nums[v].fa[0];
return;
}
void print(int u,int fa)
{
ans.push_back(u);
for(pair<int,int> v:adj[u])
{
if(v.first==nums[u].nxt||v.first==fa) continue;
print(v.first,u);
ans.push_back(u);
}
if(nums[u].nxt!=0) print(nums[u].nxt,u);
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
adj.resize(n+5);
for(int i=1,u,v,w;i<n;i++)
{
cin>>u>>v>>w;
adj[u].push_back({v,w});
adj[v].push_back({u,w});
}
lg[1]=0;
for(int i=2;i<=n;i++)
lg[i]=lg[i>>1]+1;
nums[1].dep=0,nums[1].val=0;
dfs(1,0);
for(int i=0,u,v,d,mx;i<=m;i++)
{
u=p[i][0],mx=0;
for(int x:p[i])
{
d=dis(p[i][0],x);
if(d>mx) u=x,mx=d;
}
v=u,mx=0;
for(int x:p[i])
{
d=dis(u,x);
if(d>mx) v=x,mx=d;
}
if(mx>maxd) res={u,v},maxd=mx;
}
tag(res.first,res.second);
print(res.first,0);
cout<<ans.size()<<"\n";
cout<<ans[0];
for(int i=1;i<int(ans.size());i++)
cout<<" "<<ans[i];
cout<<"\n";
return 0;
}
::::