dijkstra算法
①先取一点v[0]作为起始点,初始化dis[i],d[i]的值为v[0]到其余点v[i]的距离w[0][i],如果直接相邻初始化为权值,否则初始化为无限大;
②将v[0]标记,vis[0] = 1(vis一开始初始化为0);
③找寻与v[0]相邻的最近点v[k],将v[k]点记录下来,v[k]与v[0]的距离记为min;
④把v[k]标记,vis[k]=1;
⑤查询并比较,让dis[j]与min+w[k][j]进行比较,判断是直接v[0]连接v[j]短,还是经过v[k]连接v[j]更短,即dis[j]=MIN(dis[j],min+w[k][j]);
⑥继续重复步骤③与步骤⑤,知道找出所有点为止。
题目
http://cogs.pro/cogs/problem/problem.php?pid=415
/**************************************************************************************************** 最短路—dijkstra算法(邻接表) 将边权替换为概率,相加改为相乘,最短距离改为最大概率 ********************************************************************************************************/ #include<cstdio> #include<vector> #define MaxInt 99999999 #define MaxN 10005 #define eps 1e-8 using namespace std; struct Edge{ int next,to; double power; }e[6*MaxN]; bool s[MaxN];// 判断是否已存入该点到S集合中 double dis[MaxN]; int n,m,ed[MaxN]; void in(){ scanf("%d%d",&n,&m); int x; for(int i=1;i<=m;i++){ int j=i<<1; scanf("%d%d%lf",&x,&e[j].to,&e[j].power); e[j].power/=100; e[j].next=ed[x],ed[x]=j; if(x==1)dis[e[j].to]=e[j].power; j++; e[j].to=x;x=e[j-1].to,e[j].power=e[j-1].power; e[j].next=ed[x],ed[x]=j; if(x==1)dis[e[j].to]=e[j].power; } } void dijkstra(int v0){//v0为源点 s[v0]=1;dis[v0]=1; for(int i=1;i<n;i++){ double min1=0;int u=v0; for(int j=1;j<=n;j++){// 找出当前未使用的点j的dis[j]最小值 if(!s[j]&&dis[j]>min1+eps){ u=j;min1=dis[j];// u保存当前邻接点中距离最小(概率最大)的点的号码 } } s[u]=1; int x=ed[u]; while(x){//在通过新加入的u点路径找到离v0点更短的路径 if(dis[e[x].to]<dis[u]*e[x].power-eps)dis[e[x].to]=dis[u]*e[x].power;//更新dis x=e[x].next; } } } int perseverance(){ freopen("toura.in","r",stdin); freopen("toura.out","w",stdout); in(); dijkstra(1); printf("%.6lf",dis[n]*100); } int come_on=perseverance(); int main(){ return 0; }
堆优化
/**************************************************************************************************** 最短路—dijkstra算法堆优化(邻接表) 将边权替换为概率,相加改为相乘,最短距离改为最大概率 ********************************************************************************************************/ #include<cstdio> #include<queue> #define MaxInt 99999999 #define MaxN 10005 #define eps 1e-8 using namespace std; struct Edge{ int next,to; double power; }e[6*MaxN]; bool s[MaxN];// 判断是否已存入该点到S集合中 priority_queue<pair<double,int> > q; double dis[MaxN]; int n,m,ed[MaxN]; void in(){ scanf("%d%d",&n,&m); int x; for(int i=1;i<=m;i++){ int j=i<<1; scanf("%d%d%lf",&x,&e[j].to,&e[j].power); e[j].power/=100; e[j].next=ed[x],ed[x]=j; //if(x==1)dis[e[j].to]=e[j].power; j++; e[j].to=x;x=e[j-1].to,e[j].power=e[j-1].power; e[j].next=ed[x],ed[x]=j; //if(x==1)dis[e[j].to]=e[j].power; } } void dijkstra(int v0){//v0为源点 dis[v0]=1; q.push(make_pair( 1,v0)); while(!q.empty()){ pair<double,int>w=q.top();q.pop();// 找出当前未使用的点j的dis[j]最小值 int u=w.second; if(u==n)return; if(s[u])continue;//使用过了 s[u]=1; int x=ed[u]; while(x){//在通过新加入的u点路径找到离v0点更短的路径 if(dis[e[x].to]<dis[u]*e[x].power-eps){ dis[e[x].to]=dis[u]*e[x].power;//更新dis q.push(make_pair(dis[e[x].to],e[x].to)); } x=e[x].next; } } } int perseverance(){ freopen("toura.in","r",stdin); freopen("toura.out","w",stdout); in(); dijkstra(1); printf("%.6lf",dis[n]*100); } int come_on=perseverance(); int main(){ return 0; }
允许内部修改的堆优化(不用掌握)
#include<iostream> using namespace std; struct MinBinaryHeap{ struct node{ int key; int value; inline bool operator<(const node &t)const{ return value < t.value; } }*array; int *location,heap_size; MinBinaryHeap(int size){ heap_size=0; array=new node[size+1]; location=new int[size]; } ~MinBinaryHeap(){ delete[] array; delete[] location; } inline void update(int loc,const node& x){ //put x into array[loc] array[loc]=x; location[x.key]=loc; } void per_down(int hole){ node tem=array[hole]; while(1){ int child=hole<<1; if(child > heap_size) break; if(child!=heap_size && array[child+1] < array[child]) child++; if(array[child] < tem){ update(hole,array[child]); hole=child; }else break; } update(hole,tem); } void per_up(int hole){ node tem=array[hole]; while(hole > 1){ if(tem < array[hole>>1]){ update(hole,array[hole>>1]); hole>>=1; }else break; } update(hole,tem); } void build_heap(int *values, int n){ heap_size=n; for(int i=1;i<=n;i++){ array[i].key=i-1; array[i].value=*(values++); location[array[i].key]=i; } for(int i=heap_size>>1;i>=1;i--) per_down(i); } pair<int,int> pop(){ pair<int,int> res=make_pair(array[1].key,array[1].value); array[1]=array[heap_size--]; per_down(1); return res;; } void decrease_to(int key,int value){ array[location[key]].value=value; per_up(location[key]); } }; const int maxn=100000,INF=0x11111111;; struct graph{ int node_num,allop_pt; struct edge{ int j,w; edge *next; }*g[maxn],*pool; graph(int node_num,int edge_num):node_num(node_num){ memset(g,0,sizeof(g)); pool=new edge[2*edge_num]; allop_pt=0; } ~graph(){ delete[] pool; } inline edge* new_edge(int j,int w,edge* next){ pool[allop_pt].j=j; pool[allop_pt].w=w; pool[allop_pt].next=next; return &pool[allop_pt++]; } inline void add_edge(int i,int j,int w){ g[i]=new_edge(j,w,g[i]); g[j]=new_edge(i,w,g[j]); } }; void dijkstra(graph& g,int source, int dis[]){ bool known[maxn]={0}; for(int i=0;i<g.node_num;i++)dis[i]=INF; dis[source]=0; MinBinaryHeap heap(g.node_num); heap.build_heap(dis,g.node_num); for(int k=0;k<g.node_num;k++){ pair<int,int> tem=heap.pop(); int i=tem.first; known[i]=true; for(graph::edge* e=g.g[i];e;e=e->next){ if(!known[e->j] && dis[e->j] > dis[i]+e->w){ dis[e->j]=dis[i]+e->w; heap.decrease_to(e->j,dis[e->j]); } } } }