[WC2011]最大XOR和路径

本文介绍了一种解决特殊图论问题的方法,即在给定图中寻找从节点1到节点n的路径,使得路径上所有边的权值按异或运算得到的结果最大。通过构建深度优先搜索树,利用线性基数据结构处理环的贡献,最终选择最优路径。

题目

神仙题啊

发现题目里有一句非常重要的话“当一条边在路径中出现了多次时,其权值在计算 XOR 和时也要被计算相应多的次数

这告诉我们走一条边两次显然没有什么贡献

所以计算贡献的应该是那些走了奇数次的边

我们发现我们可以把一个环上所有的边都走奇数次遍历一个环

而两个环之间如果有路径连接的话这两个环的贡献都可以被算上,而不去计算路径的贡献

也就是连接两个环的路径走一次,环上的边走两次

所以环非常关键,我们可以选择很多的环使得我们的权值异或起来最大

这里就需要一个线性基了,我们可以配合\(dfs\)搜索树,遇到一条返祖边就找到一个环,加入线性基

尽管并没有加入所有的环,但是这些环可以将所有其他环都表示出来了

之后我们选择一条从\(1\)\(n\)的路径作为初值,从线性基里选择一些环来增广这条路径,使得异或和最大就好了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 100005
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline LL read() {
    LL x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt;LL w;}e[maxn<<1];
int head[maxn],dfn[maxn];
LL pre[maxn];
int num,n,m,cnt;
LL lb[66];
inline void add(int x,int y,LL z) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=z;}
inline void ins(LL x) {
    for(re int j=62;j>=0;--j)
        if(x>>j&1ll) {
            if(!lb[j]) {lb[j]=x;break;}
            else x^=lb[j];
        }
}
void tarjan(int x,int fa) {
    dfn[x]=1;
    for(re int i=head[x];i;i=e[i].nxt)
    if(!dfn[e[i].v]) pre[e[i].v]=pre[x]^e[i].w,tarjan(e[i].v,x);
    else ins(pre[x]^pre[e[i].v]^e[i].w); 
}
int main()
{
    n=read(),m=read();
    int x,y;LL z;
    for(re int i=1;i<=m;i++) x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
    tarjan(1,0);
    LL ans=pre[n];
    for(re int i=62;i>=0;--i) if((ans^lb[i])>ans) ans^=lb[i];
    printf("%lld\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/asuldb/p/10388772.html

以下代码在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、付费专栏及课程。

余额充值