题目链接
一、题意
给你n个点,每个点的点权是。如果,点和点连一条边权是的双向边。
问你到达点n的最短路。
多个测例。最多5个测例。
数据范围:
二、题解
表示从到且边权是的有向边。
对第位建立一个虚点。
如果,建两条有向边和。
跑dij就行了。
三、代码
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef pair<ll , int> pli ;
const int mod = 998244353 ;
const int maxn = 1e5 + 100 ;
const int maxe = 1e6 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count()) ;
struct Link
{
int num , head[maxn] ;
struct Edge
{
int v , next ;
ll w ;
} edge[maxe << 1] ;
void init()
{
num = 0 ;
memset(head , -1 , sizeof(head)) ;
}
void add_edge(int u , int v , ll w)
{
edge[num].v = v ;
edge[num].w = w ;
edge[num].next = head[u] ;
head[u] = num ++ ;
}
} link ;
struct Dij
{
ll dis[maxn] ;
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())
{
pli p = q.top() ;
q.pop() ;
int u = p.second ;
if(p.first != dis[u]) continue ; //优化,不用旧值更新。
for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
{
int v = link.edge[i].v ;
ll w = link.edge[i].w ;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w ;
q.push(make_pair(dis[v] , v)) ;
}
}
}
}
} dij ;
int n ;
ll a[maxn] ;
int main()
{
ios ;
int t ;
cin >> t ;
while(t --)
{
link.init() ;
cin >> n ;
rep(i , 1 , n) cin >> a[i] ;
rep(j , 0 , 31) rep(i , 1 , n) if(a[i] & (1ll << j)) link.add_edge(i , n + j + 1 , 1ll << j) , link.add_edge(n + j + 1 , i , 0) ;
dij.init() ;
dij.dijkstra(1) ;
if(dij.dis[n] > 1e18) cout << "Impossible\n" ;
else cout << dij.dis[n] << '\n' ;
}
return 0 ;
}