一、邻接矩阵(不多说了) G[u][v]
二、邻接表
1、动态链表(指针) 一个数组表头(u)+ struct结点(v),相链,若有权值等信息再在结点里加相应域。
2、静态链表(数组) first数组(模拟表头、u)+ 边集数组(编号e,u、v)+ next数组(模拟指针相指)。这个跟1看似有点区别(前者链的是点,后者链的是边),其实是没区别,因为要用数组实现链表,所以对1中所有结点实行e编号,意义就是“边”。
通常实现方法: 开五个数组 first[MAXN]; u[MAXM], v[MAXM], w[MAXM], next[MAXM]。
三、边集数组
就是把所有边放在一个数组里,这样就可以完成遍历所有边的操作了(很土吧= =)。通常要根据实际需要做一些辅助储存。
1、上面的数组实现邻接表就是边集数组再加上first数组和next数组。
2、前向星。跟1很相似的,区别是他对边集数组按u点(前一个端点)升序排序,使得由同一个点出发的边都集中在一起了。再加上辅助数组 f[MAXN](跟前面first数组类似的作用),存 结点i 出发的第一个边在边集数组里的位置。
所以注意到,前向星其实就是做了一个紧缩存储的处理,并且通过一次排序,省掉了next数组(静态邻接表)。当然也可以不排序,多维护一个next数组。
通常实现方法:开四个数组 f[MAXN]; u[MAXM], v[MAXM], w[MAXM]。
附:
①静态邻接表+Dijkstra+heap
- // Dijkstra+静态邻接表
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<queue>
- using namespace std;
- #define MAXN 100
- #define MAXM 100
- #define INF 1<<30
- typedef pair<int, int> pii; //(dist[v], v)
- priority_queue<pii, vector<pii>, greater<pii> > q;
- int first[MAXN];
- int u[MAXM], v[MAXM], w[MAXM], next[MAXM];
- int dist[MAXN], ins[MAXN]; // ins[] 是否在s集合中
- int n, m;
- void dijkstra(int st)
- {
- for(int i=0; i<n; i++) dist[i] = i==st? 0: INF;
- memset(ins, 0, sizeof(ins));
- q.push(make_pair(dist[st], st));
- // ins[st] = 1; //别跟spfa inq弄混,在优先队列里取出来才算是ins了
- while(!q.empty())
- {
- pii p = q.top(); q.pop();
- int x = p.second;
- if(!ins[x])
- {
- ins[x] = 1;
- for(int i=first[x]; i!=-1; i=next[i])
- {
- if(dist[v[i]] > dist[x]+w[i]) //relax
- {
- dist[v[i]] = dist[x] + w[i];
- q.push(make_pair(dist[v[i]], v[i]));
- }
- }
- }
- }//end of while
- }
- void read_graph()
- {
- scanf("%d%d", &n, &m);
- memset(first, -1, sizeof(first));
- for(int i=0; i<m; i++)
- {
- scanf("%d%d%d", &u[i], &v[i], &w[i]);
- next[i] = first[u[i]];
- first[u[i]] = i;
- }
- }
- int main()
- {
- read_graph();
- int st;
- dijkstra(scanf("%d", &st));
- for(int i=0; i<n; i++)
- {
- printf("[%d,%d]=%d\n", st, i, dist[i]);
- }
- }
②静态邻接表+spfa
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<queue>
- using namespace std;
- #define MAXN 100
- #define MAXM 100
- #define INF 1<<30
- queue<int> q;
- int first[MAXN], next[MAXM];
- struct edge
- {
- int u, v, w;
- }a[MAXM];
- int dist[MAXN], inq[MAXN];
- int n, m;
- void spfa(int st)
- {
- for(int i=0; i<n; i++) dist[i] = i==st? 0: INF;
- memset(inq, 0, sizeof(inq));
- q.push(st);
- inq[st] = 1; //反正马上就出队,这个inq可以不要
- while(!q.empty())
- {
- int u = q.front(); q.pop();
- inq[u] = 0;
- for(int e=first[u]; e!=-1; e=next[e])
- {
- int v = a[e].v;
- if(dist[v] > dist[u]+a[e].w)
- {
- dist[v] = dist[u]+a[e].w;
- if(!inq[v]) { q.push(v); inq[v] = 1; } //inq=1 !!!!
- }
- }
- }
- }
- void read_graph()
- {
- cin>>n>>m;
- memset(first, -1, sizeof(first)); //别忘了初始化 表头
- for(int e=0; e<m; e++)
- {
- cin>>a[e].u>>a[e].v>>a[e].w;
- next[e] = first[a[e].u];
- first[a[e].u] = e;
- }
- }
- int main()
- {
- read_graph();
- int st;
- cin>>st;
- spfa(st);
- for(int i=0; i<n; i++)
- {
- printf("[%d,%d]=%d\n", st, i, dist[i]);
- }
- }