The 17-th BIT Campus Programming Contest C.小L的旅行

T h e 17 − t h B I T C a m p u s P r o g r a m m i n g C o n t e s t \Huge{The 17-th BIT Campus Programming Contest} The17−thBITCampusProgrammingContest

C . 小 L 的旅行 \huge{C.小L的旅行} C.小L的旅行

题目链接:The 17-th BIT Campus Programming Contest

文章目录

题意

给出一个 n n n个点的有向图,有 m m m条边且每条边的边权为 1 1 1。每个点对应有一个魔法值,对于任意两点,若存在: a i & a j = a j a_i \& a_j = a_j ai&aj=aj,那么就存在一条从 i i i到 j j j的边,边权为 1 1 1。

求从 1 1 1到其他点的最短距离。

思路

题目要求求最短路,因此考虑使用 D i j k s t r a Dijkstra Dijkstra。由于边权都为 1 1 1,我们考虑优化 D i j k s t r a Dijkstra Dijkstra,可以使用双端队列优化掉优先队列。

然后考虑加边(将根据魔法值建的边加入到图中)。

  • 满足 a i & a j = a j a_i \& a_j = a_j ai&aj=aj,则 a j a_j aj是由 a i a_i ai的二进制下去掉若干 1 1 1得到。

  • 求一个数的所有符合 a i & a j = a j a_i \& a_j = a_j ai&aj=aj条件的值的时间复杂度太大

  • 考虑只将 a i a_i ai与其二进制下某一位1变为0得到的数之间建边

  • 这样 a i a_i ai将会到达所有能够建边的数,虽然不是强连通,但是边权都为 0 0 0。

标程

cpp 复制代码
#define int long long 
const int INF = 0x7fffffff;
const int N = 2e6 + 10; 

vector<int> d(N), dis(N, INF);
vector<PII> g[N];
vector<bool> vis(N);

void Solved() {
    int n, m; cin >> n >> m;
    for(int i = 1; i <= n; i ++ ) cin >> d[i];

    for(int i = 1; i <= m; i ++ ) {
        int x, y; cin >> x >> y;
        g[x].push_back({y, 1});
    }
    for(int i = 0; i < (1 << 20); i ++ )	//预处理出根据魔法值建的边(建在新图中)
        for(int j = 0; j < 20; j ++ )
            if((i >> j) & 1)
                g[n + i + 1].push_back({n + 1 + (i ^ (1 << j)), 0});

    for(int i = 1; i <= n; i ++ ) {			//合并两图
        g[i].push_back({n + 1 + d[i], 1});	//代表使用魔法,边权为1
        g[n + 1 + d[i]].push_back({i, 0});	//能进入新图则表示边权已+1,此时不需要加边权
    }
    
    dis[1] = 0;
    deque<int> dq;		//双端队列优化
    dq.push_back(1);
    while(dq.size()) {
        int u = dq.front(); dq.pop_front();	//每次取队列头元素
        if(vis[u]) continue;
        vis[u] = true;
        for(auto [i, j] : g[u]) {
            if(dis[i] <= dis[u] + j) continue;

            dis[i] = dis[u] + j;
            if(j) dq.push_back(i);	//优化的具体方法,及边权为1则放在末尾
            else dq.push_front(i);	//边权为0则放在开头
        }
    }

    for(int i = 1; i <= n; i ++ ) {
        if(dis[i] != INF) {
            cout << dis[i] << endl;
        } else {
            cout << "-1\n";
        }
    }
}
相关推荐
剑挑星河月7 分钟前
54.螺旋矩阵
java·算法·leetcode·矩阵
Robot_Nav32 分钟前
MPPI 局部规划器实验设计讲解
人工智能·算法·mppi
mingo_敏1 小时前
Mean-Teacher 均值教师自训练框架详解
算法·均值算法
星空露珠1 小时前
迷你世界UGc3.0脚本Wiki[剧情动画模块管理接口 Timeline]
开发语言·数据结构·算法·游戏·lua
笨笨没好名字1 小时前
Leetcode刷题python3版第一周(下)
linux·算法·leetcode
手写码匠2 小时前
手写 LLM 安全护栏:从内容审核到越狱防御的完整实现
人工智能·深度学习·算法·aigc
luj_17682 小时前
草酸与烟酸对消化及糖代谢的影响解析
服务器·c语言·开发语言·经验分享·算法
青风972 小时前
16-ADAPTRACK:基于自适应阈值的多目标跟踪匹配算法
人工智能·算法·目标跟踪
汤姆yu2 小时前
macOS系统下Aider完整安装、配置与实战使用教程
大数据·人工智能·算法·macos·github·copilot
Sam09272 小时前
【AI 算法精讲 14】TF-IDF:词频与逆文档频率
人工智能·python·算法·ai