最短路径

题目描述: N个城市,标号从0到N-1,M条道路,第K条道路(K从0开始)的长度为2^K,求编号为0的城市到其他城市的最短距离

输入: 第一行两个正整数N(2<=N<=100)M(M<=500),表示有N个城市, M条道路 接下来M行两个整数,表示相连的两个城市的编号

输出: N-1行,表示0号城市到其他城市的最短路,如果无法到达,输出-1,数值太大的以MOD 100000 的结果输出。

样例输入:
4 4
1 2
2 3
1 3
0 1
样例输出:
8
9
11

这道题数据量不是很大,可以直接用Floyd得出答案,我写的是 dijkstra 的做法,很玄学的是这道题在牛客上面有原题(点击这里跳转),我的代码在上面可以AC,但是我们学校的OJ系统不能AC,最坑的是还不给测试点信息!!!我检查了很多遍觉得我代码没问题,应该是我们学校的坑爹oj系统出错了, 希望大佬可以指出我的错误

#include<iostream>
#include<algorithm>
using namespace std;
/*
 	MAX 在这里表示无限大 ,  matrix 为邻接矩阵 , pow2_k[i] 表示 2 的 i 次幂 mod 100000 的值 , vis[i]=1 表示 i 被访问了 , 0 表示未访问 
	pre[i] 存在着 i 的前一个点 , 值为 -1 表示还没和初始节点连通 , 在这里 dis[j] 与经典的Dijkstra算法不同的是 , dis[j] 表示 j 到原始节
	点所有的边中 , 最短的一条路的最长一条边 , 2 的dis[j]次方就是那条边的长度 , 因为 2 的前 n 项和 总是小于 2 的 n+1 次方 , 所以只要比较
	一条路中最长的一条边就行了 , 由于 2 的 500 次方肯定溢出 , 所以可以用 log2(边长) 来表示长度  
	ans[i] 表示 i 到原始节点的距离 %100000 
*/	
const int MAX=99999 ;
int vis[105] , dis[105] , matrix[105][105] , n , m ,v1 , v2 , pre[105] , i , j , pos , pow2_k[505] , t , MIN , ans[505] ;
void dijkstra(){
	dis[0]=0,vis[0]=1;
	for( i=1;i<n;i++ ){
		dis[i]=matrix[0][i] ;
		if( dis[i]!=MAX )	pre[i]=0;
			else			pre[i]=-1;	
	}
	
	for( i=1;i<n;i++ ){
		MIN=MAX;
		
		// 寻找最近的点 
		for( j=1;j<n;j++ ){
			if( !vis[j]&&dis[j]<MIN ){
				MIN=dis[j];
				pos=j;
			}
		}
		
		if( MIN==MAX )	break; // 如果最短的边是 MAX , 则表示剩余的点没有和原始节点相连的了  
		
		// 每加入一个点就可以算出一个点到原始节点的距离 , 也就是这个节点的距离到前驱节点的距离, 加上前驱节点到原始节点的距离 
		ans[pos]=(ans[pre[pos]]+pow2_k[matrix[pos][pre[pos]]])%100000;
		vis[pos]=1; // 标记已访问 
		
		// 维护 dis 数组 
		for( j=1;j<n;j++ )
			if( !vis[j]&&dis[j]>max( MIN,matrix[pos][j] ) )
				dis[j]=max( MIN,matrix[pos][j] ),pre[j]=pos;
	}
}
int main()
{ 
	cin >> n >> m ;
	// 初始化数组  
	for( i=0;i<105;i++  )
		for( j=0;j<105;j++ )	matrix[i][j]=MAX;

	for( i=0,t=1;i<505;i++ ){
		pow2_k[i]=t;
		t=t*2%100000;
	}
		
	for( i=0;i<m;i++ ){
		cin >> v1 >> v2 ;
		// 如果有重复的边 , 那之前赋值的肯定比之后赋值的边小 , 所以还是用原来的值 
		if( matrix[v1][v2] == MAX )
			matrix[v1][v2]=matrix[v2][v1]= i ;	
	}
	
	dijkstra() ;
	
	for( i=1;i<n;i++ ){
		// 距离为 0 证明没有连通 , 所以输出 -1  
		if( !ans[i] )	cout<<-1<<endl;
			else		cout<<ans[i]<<endl;
	}
	return 0 ;
}

害,太弱了,洗洗睡了,明天还要改(xie)bug呢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值