题目描述: 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呢!