加权有向边
class diedge
{
private:
int v;
int w;
double wei;
public:
diedge(int from, int to, double weight)
{
this->v = from;
this->w = to;
this->wei = weight;
}
diedge()
{
v = 0;
w = 0;
wei = inf;
}
double weight()
{
return wei;
}
int from()
{
return v;
}
int to()
{
return w;
}
std::string to_string()
{
std::string s;
s = std::to_string(v) + "->" + std::to_string(w) + " " + std::to_string(wei);
}
};
加权有向图
class EWdigraph
{
private:
int v;
int e;
std::vector<std::vector<diedge>> adj;
public:
EWdigraph(int v)
{
this->v = v;
this->e = 0;
adj.resize(v);
}
int numv()
{
return v;
}
int nume()
{
return e;
}
void add_edge(diedge e)
{
adj[e.from()].push_back(e);
this->e++;
}
std::vector<diedge> iterator(int v)
{
return adj[v];
}
std::vector<diedge> edges()
{
std::vector<diedge> es;
for (int i = 0; i < v; i++)
{
for (auto e : adj[v])
{
es.push_back(e);
}
}
return es;
}
};
dijkstra
大名鼎鼎的dijkstra算法,原理并不是那么难懂,每次遍历到始点距离最近且未访问过的顶点的邻接节点,维护一个储存到每个点最短路径的数组,每次遍历时找到到每个点最短的距离并更新数组。
int dijkstra(EWdigraph g, int v, int to)
{
int n = g.numv();
bool *marked = new bool[n]; //標記是否搜索
std::vector<diedge> path(n); //路徑,可自行取捨(寫成類或者返回vector的函數,儅便利to=e.to()的時候更新path)
/*int **len = new int *[n]; //各個點到其他點的距離
for (int i = 0; i < n; i++)
{
len[i] = new int[n];
}*/
int *dis = new int[n]; //點v到其他點的距離
std::fill(marked, marked + n, 0);
//std::fill(len, len + n * n, inf);
std::fill(dis, dis + n, inf);
dis[v] = 0;
while (n-- > 0)
{
std::vector<diedge> e = g.iterator(u);
int min = inf;
int u = inf;
for(int i=0;i<n;i++)
{
if(dis[i]<min&&!marked[i]
{
min=dis[i];
u=i;
}
}
if (u == inf)
{
break;
}
marked[u] = true;
for (auto i : e)
{
//assert(i.from()=u)
if (dis[i.to()] > dis[u] + i.weight())
{
dis[i.to()] = dis[u] + i.weight();
}
}
}
return dis[to];
}
运行结果:
dijkstra算法的不足之处在于不能处理带有负权重边的图。为了解决这个问题我们会在下一期介绍bellman-find算法