【2024秋令营 #18 A】图论题(并查集 + 位运算 trick)
一开始的做法是,我就简单地以为是最短路的变式,只不过是累加变成累按位或
然后。。。就喜提 55pts
感觉很假,也不多说什么了
code
#include <bits/stdc++.h> #define re register int using namespace std; typedef long long LL; typedef pair<LL, int> PII; const int N = 1e5 + 10, M = 1e6 + 10; const LL inf = LLONG_MAX; struct Edge { int to, next; LL w; }e[M]; int top, h[N]; LL dist[N]; int n, m; bool st[N]; inline void add(int x, int y, LL w) { top ++; e[top].to = y, e[top].w = w, e[top].next = h[x]; h[x] = top; } inline void dijkstra() { priority_queue<PII, vector<PII>, greater<PII> > q; for (re i = 1; i <= n; i ++) dist[i] = inf; dist[1] = 0ll; q.push({dist[1], 1}); while (!q.empty()) { int x = q.top().second; q.pop(); if (st[x]) continue; st[x] = true; for (re i = h[x]; i; i = e[i].next) { int y = e[i].to; LL w = e[i].w; if (dist[y] > (dist[x] | w)) { dist[y] = (dist[x] | w); q.push({dist[y], y}); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; while (m --) { LL x, y, z; cin >> x >> y >> z; if (x == y) continue; add(x, y, z); add(y, x, z); } dijkstra(); cout << dist[n] << '\n'; return 0; }
观察到是按位或操作,位运算,那么多半跟二进制会扯上关系
考虑从二进制角度思考
发现题目给定
最终的答案肯定是这些 01 串组成的二进制数,再转十进制输出
那么如果考虑枚举这 62 位,要么是 0,要么是 1,发现很可做
显然,对于第 i 位,我们总是希望填 0,
具体地,一开始初始化结果全为 1,即 1111......111
从高位开始确定,到第 i 位,我们希望这一位变成 0,即 xxxx(i->)0 ... 111
那么我们可以跑一遍图,将与该状态下按位或不冲突的边标记,如果能形成 1 -> n 的通路,说明在第 i 位上填 0 合法
否则则必须填 1(因为联通图,所以此时必有通路)
那么可以用 并查集 维护,也可以 dfs 当然
时间复杂度
#include <bits/stdc++.h> #define re register int using namespace std; typedef long long LL; const int N = 5e5 + 10; int n, m, u[N], v[N], fa[N]; LL w[N]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; for (re i = 1; i <= m; i ++) cin >> u[i] >> v[i] >> w[i]; LL ans = (1ll << 63) - 1; // 我这个 ll 怎么显示得跟 1 似的 for (LL k = 62; k >= 0; k --) { for (re i = 1; i <= n; i ++) fa[i] = i; ans ^= (1ll << k); for (re i = 1; i <= m; i ++) if ((ans | w[i]) == ans) { int x = u[i], y = v[i]; if (find(x) != find(y)) { fa[find(x)] = find(y); } } if (find(1) != find(n)) ans |= (1ll << k); } cout << ans << '\n'; return 0; }
练习:
分类:
D 数据结构 - 并查集
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具