您的位置:首页 > 其它

最短路径

2017-02-22 20:08 162 查看

最短路径

题目来源:

最短路径



思路分析

由于是单源最短路径问题,所以采用Dijkstra算法

由于题目中距离很大,超出整数表示范围,所以自定义bigInteger,用于保存高精度整数。

代码

#include <stdio.h>
#include <vector>

using namespace std;

struct bigInteger{        //定义高精度整数,用于保存距离
int digit[1001];
int size;
void init(){
for(int i=0; i<1001; i++){
digit[i] = 0;
}
size = 0;
}

void set(int x){
init();
if(x==-1){             //当距离为-1表示两点之间没有直接通路
digit[0] = -1;
size = 1;
}
else{
do{
digit[size++] = x%10000;
x = x/10000;
}while(x!=0);
}
}

bigInteger operator * (int x) const{
int carry = 0;
bigInteger ret;
ret.init();
for(int i=0; i<size; i++){
ret.digit[ret.size++] = (digit[i]*x+carry)%10000;
carry = (digit[i]*x+carry)/10000;
}
if(carry!=0){
ret.digit[ret.size++] = carry;
}
return ret;
}

bigInteger operator + (const bigInteger A)const{
bigInteger ret;
ret.init();
int carry = 0;
for(int i=0; i<size||i<A.size; i++){
ret.digit[ret.size++] = (digit[i]+A.digit[i]+carry)%10000;
carry = (digit[i]+A.digit[i]+carry)/10000;
}
if(carry!=0){
ret.digit[ret.size++] = carry;
}
return ret;
}

int operator % (int x) const{
int remain = 0;
for(int i=size-1; i>=0; i--){
int temp = remain*10000+digit[i];
remain = temp%x;
}
return remain;
}

bool operator < (const bigInteger A) const{
if(size<A.size) return size<A.size;
else{
for(int i=size-1; i>=0; i--){
if(digit[i]!=A.digit[i])
return digit[i]<A.digit[i];
}
return digit[0]<A.digit[0];
}
}

}cost[501];

struct E{            //用于存储邻接链表的节点
int next;        //与节点相邻的节点编号
bigInteger c;    //与节点相邻的节点next和本节点之间的权值
};

vector<E> edge[501];   //邻接链表
bool mark[101];        //标记,当mark[j]为true时,表示结点j的最短路径长度已经得到,该结点已经加入集合k;
bigInteger dist[101];  //距离向量,当mark[i]为true时,表示已得的最短路径长度;否则,表示所有从开始结点出发,经过已知的最短路径达到集合k中的某结点,再经过一条边到达结点i的路径中最短的距离。

int main(int argc, const char * argv[]) {

int M,N;
while (scanf("%d%d", &N, &M)!=EOF){
for (int i=0; i<501; i++) {
edge[i].clear();

}
for (int i=0; i<101; i++) {
dist[i].init();
dist[i].set(-1);
mark[i] = false;
}

cost[0].set(1);
cost[1].set(2);
for(int i=0; i<M; i++){
int a,b;
scanf("%d%d", &a, &b);
if (i>1) {
cost[i] = cost[i-1]*2;
}
E temp;
temp.next = b;
temp.c = cost[i];
edge[a].push_back(temp);
temp.next = a;
edge[b].push_back(temp);
}
mark[0] = true;
int newP = 0;   //集合中新加入的点为0;
dist[0].set(0);
for(int j = 1; j<N; j++){
for(int i=0; i<edge[newP].size(); i++){
int t = edge[newP][i].next;       //与新加入的结点相邻的结点
bigInteger cc = edge[newP][i].c;  //与新加入的结点相邻结点的权值
if (mark[t]==true) {              //如果与新加入的结点相邻的结点已经在集合k,则跳过
continue;
}
bigInteger temp;
temp = dist[newP]+cc;
if(dist[t].digit[0]==-1||temp<dist[t])  //如果与新加入的结点相邻的结点之前不可达,或者通过新加入的结点到达的距离更短,则更新距离
dist[t] = temp;
}
bigInteger min;
min.size = 1001;
for (int i=0; i<1001; i++) {      //最小值初始化为一个大整数,为找最小值做准备
min.digit[i] = 9999;
}

for (int i=1; i<=N; i++) {         //遍历所有结点,找到还未放入集合k,且距离最小的结点设置为newP
if (mark[i]==true||dist[i].digit[0]==-1) {
continue;
}
if (dist[i]<min) {
min = dist[i];
newP = i;
}
}
mark[newP] = true;    //把newP放入集合k
}
for (int i=1; i<N; i++) {          //按照题目输出到所有结点的距离
printf("%d\n", dist[i]%100000);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: