剛學了LCA,寫篇題解鞏固一下node
首先題目有誤: (A是不是男生 )xor( B是不是男生)=A和B是否可以成爲情侶,這句話顯然是錯誤的qwqios
對於這道題,容易看出,對於待處理的兩個點,只要咱們找到他的最近公共祖先,問題便遊刃而解了數組
因此個人思路就是:lca+xor前綴和函數
這是個人大法師函數spa
yihuo數組就是保存當前節點到根節點的xor值code
推算了一下,對於xor前綴和有: 兩個點x,y間的的xor值=yihuo[x]^yihuo[y]io
void dfs(int f,int father,int XOR) { depth[f]=depth[father]+1; fa[f][0]=father; yihuo[f]=XOR; for(int i=1;(1<<i)<=depth[f];i++) fa[f][i]=fa[fa[f][i-1]][i-1]; for(int i=head[f];i;i=edge[i].next) if(edge[i].to!=father) dfs(edge[i].to,f,XOR^edge[i].dis); }
剩下的就是普通的lca,在深層節點向上跳的每一個過程當中class
記錄下待求的ansstream
具體實現見代碼循環
#include<iostream> #include<cstdio> using namespace std; int n,m,cnt,ans; #define N 100000+1 int fa[N][22]; struct node { int next,to,dis; } edge[N<<1]; int head[N],yihuo[N],lg[N],depth[N],a[N]; inline void add(int from,int to,int dis) { edge[++cnt].to=to; edge[cnt].next=head[from]; edge[cnt].dis=dis; head[from]=cnt; } void dfs(int f,int father,int XOR) { depth[f]=depth[father]+1; fa[f][0]=father; yihuo[f]=XOR; for(int i=1; (1<<i)<=depth[f]; i++) fa[f][i]=fa[fa[f][i-1]][i-1]; for(int i=head[f]; i; i=edge[i].next) if(edge[i].to!=father) dfs(edge[i].to,f,XOR^edge[i].dis); } void lca(int x,int y) { if(depth[x]<depth[y]) swap(x,y); while(depth[x]>depth[y]) { ans=ans xor yihuo[x] xor yihuo[fa[x][lg[depth[x]-depth[y]]-1]]; x=fa[x][lg[depth[x]-depth[y]]-1]; } if(x==y) return ; for(int i=lg[depth[x]]-1; i>=0; i--) {//2019710改,這個地方的循環開始以前寫錯了,可是提交卻ac了.. if(fa[x][i]!=fa[y][i]) { ans=ans xor yihuo[x] xor yihuo[fa[x][i]]; ans=ans xor yihuo[y] xor yihuo[fa[y][i]]; x=fa[x][i],y=fa[y][i]; } } ans=ans xor yihuo[x] xor yihuo[y] ; } int main() { scanf("%d",&n); for(int i=1; i<=n-1; i++) { int u,v,dis; scanf("%d%d%d",&u,&v,&dis); add(u,v,dis),add(v,u,dis); } for(int i=1; i<=n; i++) lg[i]=lg[i>>1]+1; dfs(1,0,0); scanf("%d",&m); for(int i=1,x,y; i<=m; i++) { ans=0; scanf("%d%d",&x,&y); lca(x,y); printf("%d\n",ans); } return 0; }
留個贊再走吧qwq