在极端情况下,图特别大,用邻接链表也会超空间限制,此时需要用到链式前向星来存图。
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int inf = INT_MAX / 10; 5 const int num = ???; 6 struct Edge{ 7 int to, next, w;//edge[i]的i就是起点,终点to,权值w,相同起点的下一条边next 8 }edge[num]; 9 int n, m, cnt; 10 int head[num];//head[i]存放以i为起点的下一条边 11 int dis[num]; 12 int inq[num];//标记节点是否在队列中 13 int neg[num];//判负圈 14 int pre[num];//记录前驱节点 15 16 void print_path(int s, int t){ 17 if(s==t) {printf("%d",s); return ;} 18 print_path(s, pre[t]); 19 printf("->%d",t); 20 } 21 22 //初始化 23 void init(){ 24 for(int i=0; i<num; ++i){ 25 edge[i].next = -1; 26 head[i] = -1; 27 } 28 cnt = 0; 29 } 30 31 //加边 32 void addedge(int u, int v, int w){ 33 edge[cnt].to = v; 34 edge[cnt].w = w; 35 edge[cnt].next = head[u];//指向上一条同起点的边 36 head[u] = cnt;//存放以u为起点的某条边edge的下标 37 cnt++; 38 } 39 40 int spfa(int s){ 41 for(int i=1; i<=n; ++i){ 42 neg[i] = 0; 43 dis[i] = inf; 44 inq[i] = false; 45 } 46 neg[s] = 1; 47 dis[s] = 0; 48 49 queue<int>q; 50 q.push(s); 51 inq[s] = true; 52 53 while(!q.empty()){ 54 int u = q.front(); 55 q.pop(); 56 inq[u] = false; 57 58 for(int i=head[u]; ~i; i=edge[i].next){//~1 即 i!=-1 59 int v = edge[i].to; 60 int w = edge[i].w; 61 if(dis[u] + w < dis[v]){ 62 dis[v] = dis[u] + w; 63 pre[v] = u; 64 if(!inq[v]){ 65 inq[v] = true; 66 q.push(v); 67 neg[v]++; 68 if(neg[v] > n) return 1;//v的更新次数超过节点个数n,即说明存在负圈 69 } 70 } 71 } 72 } 73 //print_path(s,?); 74 return 0; 75 } 76 77 int main(){ 78 while(~scanf("%d %d", &n, &m) && n && m){ 79 //初始化 80 init(); 81 // 82 while(m--){ 83 int a, b, c; 84 scanf("%d %d %d", &a, &b, &c); 85 addedge(a, b, c); 86 addedge(b, a, c); 87 } 88 // 89 spfa(1); 90 } 91 return 0; 92 }
相较原版的spfa(),结构体Edge中多了一个数据类型 next,用于存放同起点的上一条边,这也是省空间的关键所在;同时需要用到的即 head[i],用于存放以 i 为起点的某边的 edge的下标。
原文地址:https://www.cnblogs.com/0424lrn/p/12244146.html
时间: 2024-10-13 08:29:38