关于链式前向星
虽然很多人肯定都会了,我还是加深一下印象吧
首先,链式前向星需要一个结构体:
struct Edge //存边
{
int v, w, nxt;
}edge[m];
v,w分别是终点,边权
若这条边的起点为u,则nxt是u的上一条出边的编号
还需要一个数组:
int head[n];
head[u]表示目前u的最后一条出边
还需要一个变量
int cnt;
表示边的数量
那加边就可以写出来了
void add(int u, int v, int w)
{
++cnt;
edge[cnt].v = v; //终点
edge[cnt].w = w; //边权
edge[cnt].nxt = head[u]; //见下
head[u] = cnt;
}
函数的后两行对我来说比较难理解
下面说的"边"指的是u的出边
最新的边(新加的边)的上一条边就是之前的最后一条边
最新的边是edge[cnt],最新的边的上一条边是edge[cnt].nxt
之前的最后一条边是head[u],所以edge[cnt].nxt = head[u]
那最后一行就是更新目前最后一条边(即新加的边)的编号
遍历一个点的出边也很简单了:
for(int i = head[u]/*最后一条出边*/;i/*还有出边*/;i = edge[i].nxt/*切换到上一条出边*/)
附赠dijk:
#include <iostream>
#include <queue>
#include <utility>
#include <functional>
using namespace std;
struct Edge
{
int v, w, nxt;
}edge[200001];
int head[100001], cnt, n, m, s, u, v, w, dis[100001], vis[100001];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
void add(int u, int v, int w)
{
++cnt;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].nxt = head[u];
head[u] = cnt;
}
int main()
{
cin >> n >> m >> s;
for(int i = 0;i < m;++i)
cin >> u >> v >> w, add(u, v, w);
for(int i = 1;i <= n;++i)
dis[i] = 2147483647;
dis[s] = 0;
q.push(make_pair(0, s));
while(!q.empty())
{
int u = q.top().second;q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u];i;i = edge[i].nxt)
if(dis[edge[i].v] > dis[u] + edge[i].w)
dis[edge[i].v] = dis[u] + edge[i].w, q.push(make_pair(dis[edge[i].v], edge[i].v));
}
for(int i = 1;i <= n;++i)
cout << dis[i] << " ";
return 0;
}