本题是做过的第一题五星题,综合性较大——Dijkstra+高精度整数。
(在做本题的过程中突然开窍把高精度整数的int2BigInt与char2BigInt函数的功能用对=重载来代替了哈哈)
-
题目描述:
-
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
-
答疑:
- 解题遇到问题?分享解题心得?讨论本题请访问: http://t.jobdu.com/thread-7823-1-1.html
#include <iostream>
#include <vector>
#include <cstring>
#include <stack>
#include <iomanip>
#define MAXSIZE 100
using namespace std;
struct BigInt{
int digit[MAXSIZE];
int intSize;
void initBigInt(){
for (int i=0;i<MAXSIZE;i++)
digit[i]=0;
intSize=0;
}
void int2BigInt(int x){//the basic function //初值不为0,而是NULL(intSize=0)
initBigInt();
do{//注意这里与n进制化成十进制一样,也要考虑x=0的情况 ********
digit[intSize]=x%10000;
intSize++;
x/=10000;
}while (x>0);
}
void char2BigInt(char *s){
initBigInt();
int weight;
for (int i=strlen(s)-1;i>=0;i-=4){
weight=1;
for (int j=i;j>i-4&&j>=0;j--){
digit[intSize]+=(s[j]-'0')*weight;
weight*=10;
}
intSize++;
}
}
BigInt operator+(const BigInt &a)const{
BigInt sum;
sum.initBigInt();
int c=0;
int i;
for (i=0;i<intSize||i<a.intSize;i++){
sum.digit[i]=c+digit[i]+a.digit[i];
c=sum.digit[i]/10000;
sum.digit[i]%=10000;
}
sum.intSize=i;
if (c!=0)
sum.digit[sum.intSize++]=c;
return sum;
}
BigInt operator*(int x)const{//contain int2BigInt()
BigInt pro;
pro.initBigInt();
if (x==0){ //防止当x=0时return一个值为0但intSize!=0的BigInt
pro.int2BigInt(0);
return pro;
}
int c=0;
int i;
for (i=0;i<intSize;i++){
pro.digit[i]=digit[i]*x+c;
c=pro.digit[i]/10000;
pro.digit[i]%=10000;
}
pro.intSize=i;
while (c>0){
pro.digit[pro.intSize++]=c%10000;
c/=10000;
}
return pro;
}
int operator%(const int x)const{//x<10000
int temp,c=0;
for (int i=intSize-1;i>=0;i--){
temp=digit[i]+c*10000;
c=temp%x;
}
return c;
}
bool operator<(const BigInt a)const{
bool cmp=true;
if (intSize<a.intSize)
cmp=true;
else if (intSize>a.intSize)
cmp=false;
else {
for (int i=intSize-1;i>=0;i--){
if (digit[i]<a.digit[i]){
cmp=true;
break;
}
else if (digit[i]>a.digit[i]){
cmp=false;
break;
}
}
}
return cmp;
}
void print(){
for (int i=intSize-1;i>=0;i--){
cout<<setfill('0')<<setw(i==intSize-1?0:4)<<digit[i];
}
cout<<endl;
}
};
struct Edge{
int start,end;
BigInt weight;
Edge(){
}
Edge(int start,int end,BigInt weight){
this->start=start;
this->end=end;
this->weight=weight;
}
bool operator<(const Edge e){//useless
return weight<e.weight;
}
};
struct Vex{
int root;
Vex(){//initiate root
this->root=-1;
}
};
struct Graph{ //顶点下标从0开始
int graphSize;
vector<Edge> edge[MAXSIZE];
vector<Vex> vex;
int initGraph(int graphSize){
this->graphSize=graphSize;
for (int i=0;i<graphSize;i++)
edge[i].clear();
vex.clear();
}
int findRoot(int x){//useless
if (vex[x].root==-1)
return x;
else
return vex[x].root=findRoot(vex[x].root);
}
int unionSet(int x,int y){//useless
int xroot=findRoot(x);
int yroot=findRoot(y);
if(xroot!=yroot){//if x&y are not in the same set 那么说明其中一个还是初态,一次都没有并过
vex[xroot].root=yroot; //merge xset into yset
return yroot;
}
return -1;
}
};
int main(){
int n,m,x;
Graph graph;
int start,end;
BigInt weight;
bool mark[MAXSIZE];
BigInt dist[MAXSIZE];
int newPoint,minDistVex;
BigInt temp,outputCmp;
outputCmp.int2BigInt(100000);
while (cin>>n>>m){//n vexes ,m edges
//initiate
graph.initGraph(n);
newPoint=0;
for (int i=0;i<graph.graphSize;i++){
mark[i]=false;
dist[i].int2BigInt(-1);
}
mark[newPoint]=true;
dist[newPoint].int2BigInt(0);
//input edge
for (int i=0;i<m;i++){
cin>>start>>end;
weight.int2BigInt(1);//cal weight
for (int j=0;j<i;j++)
weight=weight*2;
graph.edge[start].push_back(Edge(start,end,weight));
graph.edge[end].push_back(Edge(end,start,weight));
}
//process
for (int time=0;time<n-1;time++){//每趟循环找出x到一个结点的最短路径,共n-1趟
//遍历newPoint直接相邻的结点,修改其dist
for (int i=0;i<graph.edge[newPoint].size();i++){
int end=graph.edge[newPoint][i].end;
if (mark[end]==true)//if end结点已经在x集合中,则跳过此次循环
continue;
temp=dist[newPoint]+graph.edge[newPoint][i].weight;
if (temp<dist[end]||dist[end].digit[0]==-1) //if the new dist< the old dist
dist[end]=temp;
}
//遍历dist,从mark为false的结点中找出其dist最小的结点,确定为新的newPoint,并加入x集合
int i;
for (i=0;i<graph.graphSize;i++){//initiate minDistVex
if (mark[i]==false&&dist[i].digit[0]!=-1){
minDistVex=i;
break;
}
}
for (i++;i<graph.graphSize;i++){
if (mark[i]==false&&dist[i].digit[0]!=-1&&dist[i]<dist[minDistVex])
minDistVex=i;
}
newPoint=minDistVex;
mark[minDistVex]=true;
}
//output. output dist[]
for (int i=1;i<graph.graphSize;i++){
if (outputCmp<dist[i])
cout<<dist[i]%100000<<endl;
else
dist[i].print();
}
}
return true;
}