单源最短路(dijkstra算法及堆优化)
弱化版题目链接
n^2 dijkstra模板
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cstring>
5 using namespace std;
6 int i,j,n,m,s,dis[10010];
7 bool v[10010];
8 struct Node{
9 int to;
10 int w;
11 Node *next;
12 } node[10010];
13 Node *head[10010];
14 int main()
15 {
16 scanf("%d%d%d",&n,&m,&s);
17 for(i=1;i<=n;i++)
18 {
19 dis[i]=0x7fffffff;
20 head[i]=new Node;
21 head[i]->next=NULL;
22 }
23 int x,y,w;
24 for(i=1;i<=m;i++)
25 {
26 scanf("%d%d%d",&x,&y,&w);
27 Node *p=new Node;
28 p->next=head[x]->next;
29 head[x]->next=p;
30 p->to=y;
31 p->w=w;
32 }
33 for(Node *h=head[s]->next;h;h=h->next)
34 dis[h->to]=min(dis[h->to],h->w); //注意可能有重边
35 v[s]=1;
36 dis[s]=0;
37 for(i=1;i<=n;i++)
38 {
39 int k=-1,minn=0x7fffffff;
40 for(j=1;j<=n;j++)
41 if(!v[j]&&dis[j]<minn)
42 {
43 minn=dis[j];
44 k=j;
45 }
46 if(k==-1) break;
47 v[k]=1;
48 for(Node *h=head[k]->next;h;h=h->next)
49 if(!v[h->to]&&dis[h->to]>dis[k]+h->w)
50 dis[h->to]=dis[k]+h->w;
51 }
52 for(i=1;i<=n;i++)
53 printf("%d ",dis[i]);
54 puts("");
55 return 0;
56 }
毒瘤标准版
题目链接:https://www.luogu.org/problemnew/show/P4779
直到做了这个题才发现我之前写的堆优化dijkstra一直是错的。。
这个堆优化其实很容易理解,将枚举最小值改为从堆中取出最小值,改变dis时入堆即可
用优先队列维护时必须有两个值:点的编号和当前的距离
以距离为标准从小到大排序, 每次取出最小的
以前错的原因:
堆中只维护了点的编号,以dis[x]排序
这样做在取出一个元素操作后,会更新它周围一圈元素的dis值,
若它周围一圈元素中有的在堆中,dis值被改变后,堆的性质会遭到破坏
然而由于弱化版太水了,我在做毒瘤版之前一直认为这是对的
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<queue>
5 using namespace std;
6 #define il inline
7 #define re register
8 #define N 100010
9 #define M 200010
10 int n,m,s,dis[N];
11 struct NODE{
12 int p;
13 int cost;
14 };
15 struct cmp{
16 il bool operator()(NODE ZYX,NODE YSH){
17 return ZYX.cost>YSH.cost;
18 }
19 };
20 priority_queue<NODE,vector<NODE>,cmp> q;
21 il int read(){
22 int x=0; char c=getchar();
23 while(c<'0'||c>'9') c=getchar();
24 while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
25 return x;
26 }
27 void write(int x){
28 if(x>9) write(x/10);
29 putchar(x%10+'0');
30 }
31 struct NODE{
32 int to,w,next;
33 } e[M];
34 int Head[N],num;
35 il void add(int x,int y,int w){
36 e[++num].to=y;
37 e[num].w=w;
38 e[num].next=Head[x];
39 Head[x]=num;
40 }
41 bool used[N];
42 int main()
43 {
44 n=read(); m=read(); s=read();
45 int x,y,w;
46 for(re int i=1;i<=m;i++){
47 x=read(); y=read(); w=read();
48 add(x,y,w);
49 }
50 memset(dis,127,sizeof(dis));
51 dis[s]=0;
52 q.push((NODE){s,0});
53 while(!q.empty()){
54 NODE k=q.top();
55 q.pop();
56 int u=k.p;
57 if(used[u]) continue;
58 used[u]=1;
59 for(re int i=Head[u];i;i=e[i].next){
60 int v=e[i].to;
61 if(dis[v]>dis[u]+e[i].w){
62 dis[v]=dis[u]+e[i].w;
63 q.push(NODE{v,dis[v]});
64 }
65 }
66 }
67 for(re int i=1;i<=n;i++)
68 write(dis[i]),putchar(' ');
69 return 0;
70 }
来源:oschina
链接:https://my.oschina.net/u/4311773/blog/4249140