Educational Codeforces Round 27

D

模拟


 

E

扫描线板子


 

G

题意

给你一个无向带权图,定义最短路为一条路径上各条边的权值异或,求从点1到点N的最短路径

分析

考虑整张无向图,造成answer行成差异的有:路径不一样,但最后都能到达n,说明一定行成了环,有可能是多走了一些环上的边,或者走了环的子集,但还可以走剩下的一部分,

所以问题转化为,如何解决环上xor对answer最优,这便可以用线性基了

直接dfs整张图,求出任意一个1到n,dfs过程中将环的xor值扔到线性基里,最后在去个min即可

!!!trick : 最后从线性基中取min时, 要从高位到低位xor , 这样才是最优的

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn = 1e5 + 10;

vector<pair<int,int> >G[maxn];
int dis[maxn];
bool vis[maxn];
int loops[maxn];
int a[70];
int ls;

int n,m;
int u, v, w;


void dfs(int now, int s)
{
    vis[now]=1, dis[now]=s;
    int len = G[now].size();
    for(int i = 0; i < len; i++)
    {
        int v=G[now][i].first;
        int w=G[now][i].second;
        if(!vis[v])
            dfs(v,s^w);
        else
            loops[++ls]=s^dis[v]^w;
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back(make_pair(v,w));
        G[v].push_back(make_pair(u,w));
    }
    dfs(1 ,0);
    int answer = dis[n];
    for(int i = 1; i <= ls; i++)
    {
       for(int j = 31; j>=0; j--)
       {
           if((loops[i]>>j)&1)
           {
           if(!a[j]) {a[j]=loops[i];break;}
           else loops[i]^=a[j];
           }
       }
    }
    for(int i = 31; i >= 0; i--) ///!!!!高到低
    {
        answer=min(answer, answer^a[i]);
    }
    printf("%d\n", answer);
    return 0;
}
View Code

 

posted @ 2017-11-27 20:06  Superwalker  阅读(150)  评论(0编辑  收藏  举报