【解题总结】牛客练习赛 67

总体难度递增。感觉 E 题的做法比较新奇。F 题在 51nod 有强化版本。

E 牛妹游历城市

题意:给定 n n n 个点,第 i i i 个点有权值 a i a_i ai。如果对于 i , j i, j i,j a i and ⁡ a j a_i \operatorname{and} a_j aiandaj 不为 0 0 0,那么 i , j i, j i,j 间有无向边,边权为 lowbit ⁡ ( a i and ⁡ a j ) \operatorname{lowbit}(a_i \operatorname{and} a_j) lowbit(aiandaj)。问从 1 1 1 n n n 的最短路。

我们可以依次考虑每一个位,然后把点权有相同位的点互相连一条边。但这样边的数目可能是 O ( n 2 ) O(n^2) O(n2)

更好的做法是对当前位建立一个虚拟点,设为 u u u。遍历所有点,如果 i i i 的点权满足这一位上为 1 1 1,那么连一条从 i i i u u u 的边,边权为这一位对应的二进制数;再连一条从 u u u i i i 的边,边权为 0 0 0。这样边数就下降到了至多 64 n 64n 64n。跑 Dijkstra 可以通过。

本题题解区还有些更高妙的做法。

#include <bits/stdc++.h>
#define REP(temp, init_val, end_val) for (int temp = init_val; temp <= end_val; ++temp)
#define REPR(temp, init_val, end_val) for (int temp = init_val; temp >= end_val; --temp)
using namespace std;
typedef long long ll;
int read(){
   
    int f = 1, x = 0;
    char c = getchar();
    while (c < '0' || c > '9'){
   if(c == '-') f = -f; c = getchar();}
    while (c >= '0' && c <= '9')x = x * 10 + c - '0'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值