hdu 4776 Ants Trie树+乱搞

来源:互联网 发布:充电软件 编辑:程序博客网 时间:2024/06/05 02:39

参考: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]);}}}


原创粉丝点击