链接:https://ac.nowcoder.com/acm/contest/6885/E
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
最近,牛妹天天宅在家里,真是憋死人了。他决定出去旅游。
牛妹现在正在1号点(自己家里),他决定前往n号点(牛妹想去的地方),中途可以多次经过1~n号点。
现在,已知每个点都有个权值aia_iai,如果ai&aj≠0a_i \& a_j ≠0ai&aj=0,则i号点和j号点之间连有一条双向边,权值为lowbit(ai&aj)lowbit(a_i \& a_j)lowbit(ai&aj)。
他想要最小化自己的行走距离,但是他计算不出来qaq。相信全牛客最聪明的你一定会吧!
Tips:
&\&&是位运算中and的意思,lowbit(n)的值是最大的2x2^x2x,满足2x∣n2^x | n2x∣n。
例如lowbit(5)=lowbit((101)2)=1, lowbit(8)=lowbit((1000)2)=8lowbit(5)=lowbit((101)_2)=1,\ lowbit(8)=lowbit((1000)_2)=8lowbit(5)=lowbit((101)2)=1, lowbit(8)=lowbit((1000)2)=8。
输入描述:
本题有多组数据。
第一行,输入一个数T,表示数据组数。
接下来2*T行,先输入一个数n,再输入n个数,第i个数表示aia_iai。
输出描述:
对于每组数据,输出最小的行走距离。
如果无法从1号点到达n号点,则输出“Impossible”(不含引号)。
示例1
输入
2 6 2 3 5 8 13 21 12 1 2 3 4 5 6 7 8 9 10 11 12
输出
3 5
示例2
输入
5 3 1 2 3 4 177 188 199 211 2 1 2 4 1 1 1 1 5 1 2 4 8 16
输出
1 1 Impossible 1 Impossible
备注:
数据保证1≤T≤5,1≤n≤105,1≤ai<2321\le T\le 5, 1\le n\le 10^5, 1\le a_i < 2^{32}1≤T≤5,1≤n≤105,1≤ai<232
思路:将每个权值的32位看作一个中介:如图:
然后对这个图跑一遍dijkstra.
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#define rep(i, x, n) for(int i=x; i<=n; i++)
using namespace std;
const int N = 1e5 + 100;
const int Maxn = 1e6 + 10;
typedef long long LL;
typedef pair<LL, int> pli;
int n;
LL num[N];
struct Link{
int idx, h[N];
void init(){
idx = 0;
memset(h, -1, sizeof h);
}
struct Edge{
int v, next;
LL w;
}e[Maxn << 1];
void add(int u, int v, LL w){
e[idx].v = v;
e[idx].w = w;
e[idx].next = h[u];
h[u] = idx ++;
}
}link;
struct Dij{
LL dis[N];
priority_queue< pli, vector<pli>, greater<pli> > q;
void init(){
memset(dis, 0x3f, sizeof dis);
}
void dijkstra(int s)
{
dis[s] = 0;
q.push(make_pair(0, s));
while(!q.empty())
{
// puts("debug");
pli p = q.top();
q.pop();
int u = p.second;
if(p.first != dis[u]) continue;
for(int i = link.h[u]; i != -1; i = link.e[i].next)
{
int v = link.e[i].v;
LL w = link.e[i].w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
q.push(make_pair(dis[v], v));
}
}
}
}
}dij;
int main()
{
int t;
cin>>t;
while(t--)
{
link.init();
cin>>n;
rep(i, 1, n) scanf("%lld", &num[i]);
rep(i, 1, n) rep(j, 0, 31) if(num[i] & (1 << j)) {
LL a = 1ll << j;//注意int中1<<31是负数,dij中有负权边会tl或ml
link.add(i, n+j+1, a), link.add(n+j+1, i, 0);
}
dij.init();
dij.dijkstra(1);
if(dij.dis[n] > 1e18) puts("Impossible");
else cout<<dij.dis[n]<<endl;
}
return 0;
}