E- 牛妹游历城市

E- 牛妹游历城市

一看n的范围果断放弃朴素的枚举每一对点求最短路的想法。
其实看到题目二进制,算法一般都和二进制沾边的。
可以把二进制的每个结点作为特别的中转站,所有结点连边可能的情况<=它二进制的位数,所以可以将后者作为连边的条件然后在取最短路的时候判断是不是有效的边就可以了,但是,本来是想在求最短路的时候加个判断来只有lowbit等于当前权值时进行放缩,后来想想没必要,因为两个结点有多个中转站可以走最短的那个肯定是lowbit那一个,所以直接最短路即可。

#include<queue>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cmath>
/*#include<bits/stdc++.h> */
//#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
inline LL read()
{
    LL kk=0,f=1;
    char cc=getchar();
    while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
    while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
    return kk*f;
}
void outLL(LL x)
{
	if(x<0){x=~x+1;putchar('-');}
	if(x>9)outLL(x/10);
	putchar(char(x%10+'0'));
}const int maxn=100222;
const LL INF=1e18+7;
const LL mod=1000000007;
const double PI=acos(-1);
#define pii pair<LL,LL>
#define mp(x,y) make_pair(x,y)
vector<pii>edge[maxn];
LL n;
void add(LL a,LL b,LL w)
{
	edge[a].push_back(mp(w,b));
	edge[b].push_back(mp(w,a));
}
LL dis[maxn];
bool vis[maxn];
void diji()
{
	for(int i=1;i<=n+35;++i)dis[i]=INF,vis[i]=0;
	priority_queue<pii,vector<pii>,greater<pii> >Q;
	dis[1]=0;
	Q.push(mp(0,1));
	while(!Q.empty())
	{
		LL disn,now;
		now=Q.top().second;disn=Q.top().first;Q.pop();
		if(vis[now])continue;
		vis[now]=1;
		for(auto to:edge[now])
		{
			if(!vis[to.second]&&dis[to.second]>dis[now]+to.first)
			{
				dis[to.second]=dis[now]+to.first;
				Q.push(mp(dis[to.second],to.second));
			}
		}
	}
}
int main()
{
	int T=read();
	while(T--)
	{
		n=read();
		for(int i=0;i<=n+35;++i)edge[i].clear();
		for(int i=1;i<=n;++i)
		{
			LL kk=read();
			for(int j=0;j<32;++j)
			{
				if((kk>>j)&1)
				{
					add(i,n+1+j,(1ll<<j));
				}
			}
		}
		diji();
		INF==dis[n]?printf("Impossible\n"):printf("%lld\n",dis[n]/2LL);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值