Codeforces 845G Shortest Path Problem

来源:互联网 发布:淘宝上怎么搜漆弹枪 编辑:程序博客网 时间:2024/05/16 12:32

原题

codeforces845G

题意

给一个无向带权图,求1-n的异或最短路。

解题思路

因为我们是在异或的情况下求最短路,因此环是一个特殊的存在。
我们从一个点走向环,在环内绕一圈再回到当前点,我们只会获得环的权值。也就是说,对于一个环的权值,我们可以只考虑选与不选。
如果我们在dfs遍历整个图的过程中,拆掉回边,图就成了一棵树。我们可以记录下i号点到1号点的异或距离d[i],那么任意两个点u、v之间的距离可以用d[u]^d[v]表示。
假设在dfs的时候我们找到了一条连接u、v,权值为x的回边,相当于我们就找到了一个权值为d[u]^d[v]^x的环。
将环的权值放入线性基,答案相当于就是将d[n]与线性基内的数异或能取到的最小值

代码

#include <cstdio>using namespace std;const int N=1e5+10;struct Edge{ int to,next,cost; } way[N<<1];int n,m,tot,num[N];bool vis[N];struct Base{    int x[31];    void Insert(int v)    {        if (!v) return ;        for (int i=30;i>=0;--i)            if ((1<<i)&v)            {                if (x[i]) v^=x[i];                else { x[i]=v; break; }            }    }    int Query(int v)    {        for (int i=30;i>=0;--i)            if ((v^x[i])<v) v^=x[i];        return v;    }}base; void AddEdge(int a,int b,int c) { way[++tot]=(Edge){b,num[a],c}; num[a]=tot; }void Init(){    scanf("%d%d",&n,&m);    int u,v,cost;    for (int i=1;i<=m;++i)    {        scanf("%d%d%d",&u,&v,&cost);        AddEdge(u,v,cost);        AddEdge(v,u,cost);      }}int dis[N];void Dfs(int x){    vis[x]=1;    for (int i=num[x];i;i=way[i].next)    {        int v=way[i].to;        if (!vis[v])        {            dis[v]=dis[x]^way[i].cost;            Dfs(v);        }else base.Insert(dis[v]^dis[x]^way[i].cost);    }}void Solve(){    Dfs(1);    printf("%d\n",base.Query(dis[n]));}int main(){    Init();    Solve();    return 0;}
原创粉丝点击