[wc2011]Xor

Xor
给定一个n(n≤50000) 个点m(m≤10000) 条边的无向图,每条边上有一个权值。请你求一条从1到n的路径,使得路径上的边的异或和最大。


线性基
任意选一条道路,作为初始答案
对所有环求异或和
对所有数求线性基,最优解一定是当前道路异或上一些环
贪心修改答案

冗长代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define File(x) "test."#x
#define For(i,s,e) for(int i=(s); i<=(e); i++)
#define Rep(i,s,e) for(int i=(s); i>=(e); i--)
using namespace std;

const int N=50000+15,C=10+5,inf=0x7fffffff;
typedef long long LL;
struct Node{
    int x,next; LL w;
}T[N];

int n,m,h[N],len,cnt;
LL ans,cir[N],xs[N];//xor_sum ->xs
bool vis[N];

void addEdge(int x, int y, LL w){
    T[++len]=(Node){y,h[x],w}; h[x]=len;
}
void getCircle(int x, int last){
    vis[x]=true;
    for(int p=h[x]; p; p=T[p].next){
        int v=T[p].x;
        if(v==last) continue;
        if(!vis[v]) xs[v]=xs[x]^T[p].w, getCircle(v, x);
        else cir[++cnt]=xs[x] ^ xs[v] ^ T[p].w;
    }
}

int main()
{
    freopen(File(in),"r",stdin);
    freopen(File(out),"w",stdout);

    scanf("%d%d",&n,&m);
    For(i,1,m){
        int u,v;
        LL w;
        scanf("%d%d%lld",&u,&v,&w);
        addEdge(u,v,w); addEdge(v,u,w);
    }
    getCircle(1, 0);
    ans=xs[n];//初始答案
//  For(i,1,cnt) printf("%d\n",cir[i]);
    sort(cir+1, cir+1+cnt);//应该没啥用
    cnt=unique(cir+1, cir+1+cnt)-cir-1;

//  printf("%lld\n",ans);

    for(int i=63; i>=0; i--){
        if(!(ans&(1LL<<i))){//如果这位是 0, 看能否变成 1(这样会更大)
            int fp=0;
            For(j,1,cnt){
                if(cir[j]&(1LL<<i)){
                    fp=j; break;
                }
            }
            if(!fp) continue;
//          printf("%d %d %d\n",i,fp,cir[fp]);
            ans^=cir[fp];
            For(j,fp+1,cnt){
                if(cir[j]&(1LL<<i)) cir[j]^=cir[fp];//make_it_线性基ing
            }
            cir[fp]=0;
        } else {//如果这位是 1,就不能选这位是 1的数(因为这样会让答案变小)
            int fp=0;
            For(j,1,cnt){
                if(cir[j]&(1LL<<i)){
                    fp=j; break;
                }
            }
            if(!fp) continue;
            For(j,fp+1,cnt){
                if(cir[j]&(1LL<<i)) cir[j]^=cir[fp];
            }
            cir[fp]=0;
        }
    }

    printf("%lld\n",ans);

    return 0;
}
以下代码在radasm编译后打开.exe无法生成窗口_ProcWinMain proc uses ebx esi edi hWnd,wMsg,wParam,lParam LOCAL @stPs:PAINTSTRUCT LOCAL @hDc mov eax,wMsg .if eax==WM_CREATE mov Score,0 mov PlayFlag,1 mov Velocity,400 invoke LoadIcon,hInstance,ID_ICO invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax .elseif .else invoke DefWindowProc,hWnd,wMsg,wParam,lParam ret .endif xor eax,eax ret _ProcWinMain endp ;******************************************************************** ;创建窗口 ;******************************************************************** WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL @wc:WNDCLASSEX LOCAL @msg:MSG LOCAL @hwnd:HWND mov @wc.cbSize,sizeof WNDCLASSEX mov @wc.style,CS_HREDRAW or CS_VREDRAW mov @wc.lpfnWndProc,offset _ProcWinMain mov @wc.cbClsExtra,NULL mov @wc.cbWndExtra,NULL push hInstance pop @wc.hInstance invoke LoadMenu,hInstance,IDR_MENU mov hMenu,eax mov @wc.hbrBackground,COLOR_BTNFACE+1 mov @wc.lpszMenuName,NULL mov @wc.lpszClassName,offset ClassName invoke LoadIcon,hInstance,ID_ICO mov @wc.hIcon,eax mov @wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov @wc.hCursor,eax invoke RegisterClassEx,addr @wc invoke CreateWindowEx,WS_EX_CLIENTEDGE or WS_EX_WINDOWEDGE,\ addr ClassName,addr AppName,\ WS_MINIMIZEBOX or WS_SYSMENU,\ CW_USEDEFAULT,CW_USEDEFAULT,\ 132h,179h,NULL,hMenu,hInst,NULL mov @hwnd,eax invoke ShowWindow,@hwnd,CmdShow invoke UpdateWindow,@hwnd .while TRUE invoke GetMessage,addr @msg,NULL,0,0 .break .if(!eax) invoke TranslateMessage,addr @msg invoke DispatchMessage,addr @msg .endw mov eax,@msg.wParam ret WinMain endp start: invoke GetModuleHandle,NULL mov hInstance,eax invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT invoke ExitProcess,eax end start
最新发布
03-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值