【Poj 3764】The xor-longest Path 字典序+贪心

The xor-longest Path

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 5242 Accepted: 1140

Description

In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:

{xor}length(p)=\oplus{e \in p}w(e)

⊕ is the xor operator.

We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?  

Input

The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.

Output

For each test case output the xor-length of the xor-longest path.

Sample Input
4
0 1 3
1 2 4
1 3 6

Sample Output
7

Hint

The xor-longest path is 0->1->2, which has length 7 (=3 ⊕ 4)

题意:在一棵树中找最大的XOR道路;
思路:1.异或性质:a^b=(a^c)^(b^c)—>dfs取任意根做异或;
2.n^2的两次FOR—>字典序时间换空间找特定序列,枚举+贪心以0,1,做关键字在字典树上找当前最优解;
3.*小优化:FOR时find后insert,保证最优解仍存在;

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#define clr(p) memset(p,0,sizeof(p))
#define MAXN 110500 
using namespace std;
int head[MAXN],next[MAXN*2],to[MAXN*2],val[MAXN*2];
int XOR[MAXN];
int tot;
int sum;
int n;
struct node{
    int ch[2];
    void init()  {
    ch[0]=ch[1]=0;
    } 
}t[31*MAXN];
void add(int aa,int bb,int cc)
{
    to[++tot]=bb;
    val[tot]=cc;
    next[tot]=head[aa];
    head[aa]=tot;
}
void dfs(int x,int now,int pre)
{
    XOR[x]=now;
    for(int i=head[x];i!=-1;i=next[i])
    { 
        int v=to[i];
        if(v==pre) continue; 
        dfs(v,now^val[i],x);
    }
}
void insert(int x)
{
    int ret=0,now=0;
    for(int j=30;j>=0;j--)
    {
        if((1<<j)&x) ret=1;
        else ret=0;
        if(!t[now].ch[ret]) t[now].ch[ret]=++sum;
        t[sum].init();
        now=t[now].ch[ret];
    }
}
int solve(int x)
{   
    int ret=0;
    int now=0;
    for(int i=30;i>=0;i--)
    {
        int p=(1<<i)&x;
        if(p) p=0;
        else p=1; 
        if(t[now].ch[p])    ret+=(1<<i);    
        else    p^=1;   
        now=t[now].ch[p];

    }
    //maintain,to find the curent best sol. for whats after x;
    return ret;
}

int main()
{
    while( (scanf("%d",&n))!=EOF )
    {
        sum=tot=0;
        memset(head,-1,sizeof(head));
        clr(to),clr(next),clr(val),clr(XOR);
        t[0].init();
        int aa,bb,cc;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&aa,&bb,&cc);
            aa++;
            bb++;
            add(aa,bb,cc);
            add(bb,aa,cc);
        }
        dfs(1,0,-1);
        int ans=0;
        for(int i=1;i<=n;i++)
        insert(XOR[i]);
        for(int i=1;i<=n;i++)  ans=max(ans,solve(XOR[i]));

        printf("%d\n",ans);
    }
}   

类似题:codeforces 282E - Sausage Maximization

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#define LL long long 
using namespace std;
int n;
LL pre[100005],suf[100005],a[100005];
struct node{
    int ch[2];
}t[100005*50];
LL ans;
int tot=0;
inline void add(LL x)
{
    int now=0;
    for(int i=50;i>=0;i--)
    {
        LL tmp=(1LL<<i)&x;
        if(tmp) tmp=1;
        if(!t[now].ch[tmp])  t[now].ch[tmp]=++tot;
        now=t[now].ch[tmp];
    }
}
inline LL solve(LL x)
{
    LL ret=0;
    int now=0;
    for(int i=50;i>=0;i--)
    {
        LL tmp=(1LL<<i)&x;
        if(tmp) tmp=0;
        else tmp=1;
        if(t[now].ch[tmp])   ret+=(1LL<<i);
        else tmp^=1;
        now=t[now].ch[tmp]; 
    }
    return ret;
}


int main()
{
    scanf("%d",&n);
    ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%I64d",&a[i]);
        pre[i]=pre[i-1]^a[i];
    }
    for(int i=n;i>=1;i--)
    suf[i]=suf[i+1]^a[i];
    for(int i=1;i<=n+1;i++)
    {
        add(pre[i-1]);
        ans=max(ans,solve(suf[i]));
    }
    printf("%I64d",ans);
}

你可能感兴趣的:(poj,字典序)