XOR最短路径 BFS

解题思路分析:

  1. 问题理解:

    • 需要在有向图中找到从1到N的任意行走(允许重复访问节点和边)

    • 目标是使路径上所有边权重的异或值最小

  2. 关键观察:

    • 异或操作的性质:a ^ b ^ b = a(走两次同一条边会抵消)

    • 因此可以允许路径中出现"来回走"的情况来调整异或值

  3. 算法选择:

    • 使用BFS遍历所有可能的异或值

    • 维护vis[x][k]数组记录到达节点x时异或值为k的可能性

    • 由于边权<2^10,异或值最多2047种可能,空间可以接受

  4. 复杂度分析:

    • 时间复杂度:O(N*2048) ≈ 2e6,可以接受

    • 空间复杂度:O(N*2048) ≈ 8e6,可以接受

  5. 算法正确性:

    • BFS保证了我们能探索所有可能的路径组合

    • 通过维护异或值而不是路径长度,可以找到最优解

    • 最后遍历所有可能的异或值找到最小值

  6. 边界处理:

    • 无解时输出-1

    • 正确处理自环边和重边的情况

  7. 优化点:

    • 可以提前终止搜索,当找到异或值为0时直接返回

    • 可以使用位运算优化异或计算

#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;

// 常量定义
const int N = 2e3 + 10;      // 最大顶点数的两倍
const int inf = 0x3f3f3f3f;  // 无穷大值
vector<pii> g[N];            // 邻接表存储图,g[x]存储从x出发的边(pair<终点,权重>)
int vis[N][N];               // vis[x][k]标记是否可以通过某路径到达x点且异或值为k
int n, m;                    // 顶点数和边数

// BFS广度优先搜索函数
void bfs(int s)
{
    queue<pii> q;            // 队列存储待处理的节点和当前异或值
    vis[s][0] = 1;           // 起点s的初始异或值为0
    q.push({s, 0});          // 将起点加入队列
    
    while(q.size())
    {
        int x = q.front().first;     // 当前节点
        int k = q.front().second;    // 当前路径的异或值
        q.pop();
        
        // 遍历当前节点的所有邻接边
        for(int i = 0; i < g[x].size(); i++)
        {
            int y = g[x][i].first;   // 邻接节点
            int z = g[x][i].second;  // 边权重
            int w = k ^ z;           // 新的异或值
            
            // 如果这个状态(y,w)未被访问过
            if(!vis[y][w]){
                vis[y][w] = 1;       // 标记为已访问
                q.push({y, w});     // 加入队列继续处理
            }
        }
    }
}

int main()
{
    cin >> n >> m;  // 输入顶点数和边数
    
    // 构建邻接表
    for(int i = 1; i <= m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        g[x].push_back({y, z});  // 添加有向边
    }
    
    bfs(1);  // 从顶点1开始BFS
    
    int ans = inf;
    // 遍历所有可能的异或值(0到2047)
    for(int i = 0; i <= (2 << 10); i++)
        if(vis[n][i])  // 如果存在到n点且异或值为i的路径
            ans = min(ans, i);  // 更新最小值
    
    if(ans == inf) 
        cout << -1;  // 无解情况
    else 
        cout << ans; // 输出最小异或值
    
    return 0;
}

 

posted @ 2025-06-18 19:50  CRt0729  阅读(25)  评论(0)    收藏  举报