牛客IOI周赛26-普及组D-建图思维,虚点,最短路

题目大意:

给你n个数. 两个数之间有一条 a i + a j a_i+a_j ai+aj的边,当 a i & a j ≠ 0 a_i\&a_j \neq 0 ai&aj=0.问从1开始的最短路.

题目思路:

拆位来看,所有 a x & 2 k ≠ 0 a_x\&2^k \neq 0 ax&2k=0的数两两之间都有边.拉一个 虚 点 虚点 连向他们。开31个虚点跑最短路即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
ll a[maxn];
int bk[maxn];
ll dist[maxn];
struct Node{
    ll id , dist;
    bool operator < (const Node & a) const {
        return dist > a.dist;
    }
};
vector<pair<int,ll>> e[maxn + 50];
int main()
{
    ios::sync_with_stdio(false);
    int n; cin >> n;
    for (int i = 1 ; i <= n ; i++) {
        cin >> a[i];
        // 高效建图
        for (int j = 0 ; j <= 30 ; j++){
            if (a[i] & (1 << j)){
                e[i].pb({n + j + 1 , a[i]});
                e[n + j + 1].pb({i , a[i]});
            }
        }
    }
    memset(dist , -1 , sizeof dist);
    priority_queue<Node> q;
    q.push({1 , 0});
    dist[1] = 0;
    while (q.size()){
        Node tmp = q.top();q.pop();
        int id = tmp.id;
        if (bk[id]) continue;
        bk[id] = 1;
        for (auto g : e[id]){
            ll v = g.first , w = g.second;
            if (dist[v] == -1 || dist[v] > dist[id] + w){
                dist[v] = dist[id] + w;
                q.push({v , dist[v]});
            }
        }
    }
    for (int i = 1 ; i <= n ; i++){
        cout << dist[i] << " ";
    }
    cout << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值