BZOJ2115: [Wc2011] Xor

Description

Input

第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。

Output

仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。

Sample Input

5 7
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2

Sample Output

6

HINT

 

 
因为是异或,不能走回头路,答案一定是一条1~n的链与几个环的异或和
首先随便选出一条链,(为什么随便都可以?如果有多条路径,这条链不合适,它与其他链也是个环,最后还是会被异或掉)
然后我们想要得到一个环的异或值,就顺着走一遍走回来就可以了
然后就和hdu3949一样了,感觉2的
代码如下:
//MT_LI
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node
{
    int x,y,next;
    ll c;
}a[210000];int len,last[51000];
void ins(int x,int y,ll c)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
}
bool v[51000];
ll f[2110000],d[51000];
int tot,n,m;
void dfs(int x)
{
    v[x]=true;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(!v[y])d[y]=d[x]^a[k].c,dfs(y);
        else f[++tot]=d[x]^a[k].c^d[y];
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;ll c;
        scanf("%d%d%lld",&x,&y,&c);
        ins(x,y,c);ins(y,x,c);
    }
    memset(v,false,sizeof(v));
    dfs(1);
    ll ans=d[n];
    for(int i=1;i<=tot;i++)
    {
        for(int j=i+1;j<=tot;j++)
            if(f[i]<f[j])
                swap(f[i],f[j]);
                
        if(f[i]==0){tot=i-1;break;}
        for(int k=62;k>=0;k--)
            if(f[i]&(1ll<<k))
            {
                for(int j=i+1;j<=tot;j++)
                    if(f[j]&(1ll<<k))f[j]^=f[i];
                break;
            }
    }
    for(int i=1;i<=tot;i++)ans=max(ans,ans^f[i]);
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-08-12 15:38  MT_LI  阅读(126)  评论(0编辑  收藏  举报