spfa算法邻接表实现

“东信杯”广西大学第一届程序设计竞赛(同步赛)

• 题意:在有向图选取一条路径使得路径中边权乘积最短,其中边
权必定为2的正整数次幂。
• 考虑最短路模型是边权相加,那么我们只需要将乘法转化为加法
也就是将边权对2取对数,再计算最短路得到最短长度ans,最后
我们的答案就是2^ans % (1e9+7),最后计算幂时会溢出,所以暴
力ans次乘以2,每次都对其取模即可

//题意:
//在有向图选取一条路径使得路径中边权乘积最短,其中边权必定为2的正整数次幂。
// 考虑最短路模型是边权相加,那么我们只需要将乘法转化为加法也就是将边权对2取对数,再计算最短路得到最短长度ans,
//最后我们的答案就是2^ans % (1e9+7),最后计算幂时会溢出,所以暴力ans次乘以2,每次都对其取模 
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=5e6+7;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int M,N,S,T,cnt;//cnt记录结构数组的位置1,2,3,4,5。。。。。 
struct Edge{
	int next;//指向下一个结构数组的位置 
	int to;//目的地 
	int dis;//权值 
}edge[maxn];
int head[maxn],visit[maxn],dis[maxn];//head数组记录以u为起点的邻接表表头在结构数组中的位置
//visit数组记录点是否在队列中 ,dis数组存入起点到各个点的最短距离 
void add(int u,int v,int w)
{
	edge[++cnt].next =head[u];//以u为起点的邻接表表头的下一个位置 
	edge[cnt].to =v;
	edge[cnt].dis =w;
	head[u]=cnt;//记录u当前位置 
 } 
 queue q;//定义一个队列 
void spfa()
{
	for(int i=1;i<=N;i++)
	dis[i]=inf;//初始化dis数组; 
	dis[S]=0;
	visit[S]=1;
	q.push(S);//起点入队 
	while(!q.empty() )//判断队列是否为空
	{
		int u,v;
		u=q.front() ;//记录队首 
		q.pop() ;//队首出队; 
		visit[u]=0;//取消标记,u点不再队列中,这与bfs不一样
		for(int i=head[u];i;i=edge[i].next )
		{
			v=edge[i].to ;
			if(dis[v]>dis[u]+edge[i].dis )
			{
				dis[v]=dis[u]+edge[i].dis;
				if(!visit[v])//如果v点不再队列中,就将其入队
				{
					q.push(v);
					visit[v]=1;//标记; 
				 } 
			}
		 } 
	 } 
}
int main()
{
	int u,v,w;
	cin>>N>>M>>S>>T;
	while(M--)
	{
		cin>>u>>v>>w;
		w=log2(w);//先求对数,否则此题的数据过大会爆范围;
		add(u,v,w);//赋值函数 
	}
	spfa(); 
	if(dis[T]!=inf)
	{
		ll ans=1;
		for(int i=1;i<=dis[T];i++)
		{
			ans=ans*2%mod;
		}
		printf("%d\n",ans);
	}
	else
	printf("-1\n");
	
}

 

你可能感兴趣的:(spfa算法邻接表实现)