您的位置:首页 > 其它

bzoj2115 [Wc2011] Xor(图论+线性基)

2018-02-27 07:16 169 查看
题目链接

分析:

首先有一个小技巧,是本题的关键:

任意一条11到nn的路径的异或和,都可以由任意一条11到nn路径的异或和与图中的一些环的异或和来组合得到

这个怎么理解呢 ?

我们可以找到一条主干线

而路上有环都可以归结成一下情况:



权值就是一条单路径(1->n)+所有环

一遍dfs把ta们求出来就可以了

复杂度O(n+m)

求出线性基,里面存储的就是各个环的xor值

因为我们用高斯消元把线性基消成了上三角形,所以在统计答案的时候

需要判断一下:
if (b[j]&&((ans^b[j])>ans))


tip

注意a数组的大小

因为dis是ll类型的,以后判断该位上是否是一的时候都这么写:
a[i]>>j&1


#include<bits/stdc++.h>
#define ll long long

using namespace std;

const int N=50005;
struct node{
int y,nxt;
ll v;
};
node way[N<<2];
int st
,tot=0,n,m,cnt=0;
ll a[N*20],b[100],dis
;
bool vis
;

void add(int u,int w,ll z) {
tot++;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
tot++;way[tot].y=u;way[tot].v=z;way[tot].nxt=st[w];st[w]=tot;
}

void dfs(int now) {
vis[now]=1;
for (int i=st[now];i;i=way[i].nxt)
if (vis[way[i].y]) {               //环
a[++cnt]=dis[now]^dis[way[i].y]^way[i].v;
} else {
dis[way[i].y]=dis[now]^way[i].v;
dfs(way[i].y);
}
}

void cal() {
ll ans=dis
;               //主干线
for (int i=1;i<=cnt;i++)
for (int j=63;j>=0;j--)
if (a[i]>>j&1) {
if (b[j]) a[i]^=b[j];
else {
b[j]=a[i];
break;
}
}
for (int j=63;j>=0;j--)
if (b[j]&&((ans^b[j])>ans))
ans^=b[j];
printf("%lld",ans);
}

int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {
int u,w;ll z;
scanf("%d%d%lld",&u,&w,&z);
add(u,w,z);
}
dfs(1);
cal();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: