hdu 4776 Ants Trie树+乱搞

参考:http://www.csdn123.com/html/itweb/20131111/216497.htm

代码写的真心挫,在看了题解的算法后,自己去实现,调了好长时间才弄对。代码能力真是不行,难怪区域赛被虐成狗。。。

算法,是参照以上链接的,不多提,就说下我写的时候遇到的问题:

首先,在找次大的时候,不要写成递归的,我最开始是写递归的,但是死活都是爆栈,只好代码都删了重新写的。。。

然后,由于到根的异或和可以相同,所以在插入到字典树中的时候要记录数目,然后找次大的时候要考虑好这个细节!如果找以u为起点,v为终点的次大的时候,如果找到的叶子是u所在的叶子的时候的情况需要怎么处理。。。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 100100;
typedef long long ll;
struct Side{
	int to,next;
	ll w;
}side[maxn*2];
int node[maxn],top;
ll val[maxn];
void add_side(int u,int v,ll w){
	side[top]=(Side){v,node[u],w};node[u]=top++;
	side[top]=(Side){u,node[v],w};node[v]=top++;
}
bool vis[maxn];
void dfs(int u){
	vis[u]=true;
	for(int i=node[u];i!=-1;i=side[i].next){
		int v=side[i].to;
		if(vis[v])continue;
		val[v]=val[u]^side[i].w;
		dfs(v);
	}
}
ll bit[60];
int end[maxn],root=1,cnt;
struct Node{
	int ch[2];
	int cnt;
	int fa;
	ll val;
}trie[maxn*60];
struct E{
	ll val;
	int u,x,cnt;
	friend bool operator < (const E &a,const E &b){
		return a.val<b.val;
	}
};
priority_queue<E>q;
ll ans[2*maxn];
int find_max(int p,ll val,int b){
	for(int i=b;i>=0;i--){
		int t=(val&bit[i])?1:0;
		if(trie[p].ch[t^1])p=trie[p].ch[t^1];
		else p=trie[p].ch[t];
	}
	return p;
}
bool find_next(E &e){
	if(e.cnt>0){
		e.cnt--;
		return true;
	}
	if(e.x==end[e.u])return false;

	int u=e.u,x=e.x,cnt=e.cnt;
	//cout<<u<<' '<<x<<' '<<endl;
	int b=0;
	while(x!=root){
		int fa=trie[x].fa;
		int b1=(val[u]&bit[b])?1:0;
		int b2=(trie[x].val&1)?1:0;
		if(b1^b2){
			if(trie[fa].ch[b1]){
				x=find_max(trie[fa].ch[b1],val[u],b-1);
				break;
			}else x=fa;
		}else{
			x=fa;
		}
		b++;
	}
	e.x=x;
	e.cnt=trie[x].cnt-1;
	e.val=val[u]^trie[x].val;
	if(end[u]==x){
		e.cnt--;
		if(e.cnt<0)return false;
	}
	return true;
}
int main(){
	bit[0]=1;
	for(int i=1;i<60;i++)bit[i]=bit[i-1]*2;
	int n;
	while(~scanf("%d",&n)&&n){
		while(!q.empty())q.pop();
		memset(node,-1,sizeof(node));
		memset(ans,-1,sizeof(ans));
		memset(vis,false,sizeof(vis));
		top=0;
		for(int i=1;i<n;i++){
			int u,v;ll w;
			scanf("%d%d",&u,&v);cin>>w;
			add_side(u,v,w);
		}
		val[1]=0;
		dfs(1);
		trie[root].ch[0]=trie[root].ch[1]=0;
		trie[root].cnt=trie[root].fa=0;
		cnt=2;
		E tmp;
		for(int i=1;i<=n;i++){
			int p=root;
			for(int j=59;j>=0;j--){
				int b1=(bit[j]&val[i])?1:0;
				if(trie[p].ch[b1]==0){
					trie[cnt].ch[0]=trie[cnt].ch[1]=0;
					trie[cnt].val=trie[p].val*2+b1;
					trie[cnt].fa=p;
					trie[cnt].cnt=0;
					trie[p].ch[b1]=cnt++;
				}
				p=trie[p].ch[b1];
				//cout<<trie[p].val<<endl;
			}
			trie[p].cnt++;
			end[i]=p;
		}
		for(int i=1;i<=n;i++){
			int x=find_max(root,val[i],59);
			tmp.x=x;
			tmp.u=i;
			tmp.cnt=trie[x].cnt-1;
			tmp.val=trie[x].val^val[i];
			if(end[tmp.u]==x)tmp.cnt--;
			//printf("%d %lld %lld\n",i,val[i],tmp.val);
			if(tmp.x!=end[i]||tmp.cnt>=0)q.push(tmp);
		}
		//tmp = q.top();
		//printf("%lld\n",tmp.val);
		for(int k=1;k<=200000&&!q.empty();k++){
			tmp=q.top();q.pop();
			ans[k]=tmp.val;
			//printf("%d %lld\n",k,ans[k]);
			if(find_next(tmp))q.push(tmp);
		}
		int m;
		scanf("%d",&m);
		for(int i=0;i<m;i++){
			int k;
			scanf("%d",&k);
			printf("%I64d\n",ans[k]);
		}
	}
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/wh2124335/article/details/16829805
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞