前言
恕我直言,在负边权面前,Dijkstra就是ZZ…
1.算法思想
用一个dis[]数组储存出发点到该点的最短距离,用一个FIFO队列来记录待优化的结点,每次将队首结点取出,并用该结点的dis来更新与其直接连通的结点的dis值,如果一个点的dis值被修改了而且该点不在队列中,则将其放在队尾;不断重复该过程直到队列为空。此时,dis[]数组里储存的便是每个点到出发点的最短距离。
2.SPFA模板题
【题目链接】
洛谷【3371】
【题目描述】
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
【输入格式】
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。
接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。
【输出格式】
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)
【输入样例】
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
【输出样例】
0 2 4 3
【程序】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include<cstdio> #include<iostream> #include<queue> #define MAX 2147483647 #define MIN 0 #define M 500500 using namespace std; int n,m,s; struct E{ int to,next,w; }e[M]; int tope,head[M]; inline void ae(int x,int y,int z) { tope++;e[tope].to=y;e[tope].next=head[x];head[x]=tope;e[tope].w=z; } queue<int>q; int dis[M]; bool in[M]; inline void spfa(int x) { int topp; for(int i=1;i<=n;++i) { dis[i]=MAX; } q.push(x);dis[x]=0;in[x]=1; do { topp=q.front(); q.pop(); in[topp]=0; for(int i=head[topp],p=e[i].to;i;i=e[i].next,p=e[i].to) { if(dis[topp]+e[i].w<dis[p]) { dis[p]=dis[topp]+e[i].w; if(!in[p]) { q.push(p); in[p]=1; } } } }while(!q.empty()); } int main() { scanf("%d%d%d",&n,&m,&s); int ta,tb,tc; for(int i=1;i<=m;++i) { scanf("%d%d%d",&ta,&tb,&tc); ae(ta,tb,tc); } spfa(s); for(int i=1;i<=n;++i) { printf("%d ",dis[i]); } return 0; }
|
3.最短路计数
【题目链接】
洛谷【1144】
【题目描述】
给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。
【输入格式】
输入第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
【输出格式】
输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。
【输入样例】
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
【输出样例】
1
1
1
2
4
【程序】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| #include<cstdio> #include<iostream> #include<queue> #define MAX 2147483647 #define MIN 0 #define M 500500 #define MOD 100003 using namespace std; int n,m,s; struct E{ int to,next,w; }e[M]; int tope,head[M]; inline void ae(int x,int y,int z) { tope++;e[tope].to=y;e[tope].next=head[x];head[x]=tope;e[tope].w=z; } queue<int>q; int dis[M],cnt[M]; bool in[M]; inline void spfa(int x) { int topp; for(int i=1;i<=n;++i) { dis[i]=MAX; } cnt[x]=1; q.push(x);dis[x]=0;in[x]=1; do { topp=q.front(); q.pop(); in[topp]=0; for(int i=head[topp],p=e[i].to;i;i=e[i].next,p=e[i].to) { if(dis[topp]+e[i].w<dis[p]) { dis[p]=dis[topp]+e[i].w; cnt[p]=cnt[topp]%MOD; if(!in[p]) { q.push(p); in[p]=1; } } else { if(dis[topp]+e[i].w==dis[p]) cnt[p]=(cnt[p]+cnt[topp])%MOD; } } }while(!q.empty()); } int main() { scanf("%d%d",&n,&m); int ta,tb; for(int i=1;i<=m;++i) { scanf("%d%d",&ta,&tb); ae(ta,tb,1); ae(tb,ta,1); } spfa(1); for(int i=1;i<=n;++i) { if(dis[i]==MAX) printf("0\n"); else printf("%d\n",cnt[i]); } return 0; }
|