单源最短路(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 }