带权边的构造
/*带权图的边*/
class edge
{
private:
int v;
int w;
double wei;
public:
edge(int v, int w, double weight)
{
this->v = v;
this->w = w;
this->wei = weight;
}
double weight()
{
return wei;
}
int either()
{
return v;
}
int other(int ver)
{
if (ver == v)
return w;
else
return v;
}
int cmpt(edge that)
{
if (this->weight() < that.weight())
return -1;
else if (this->weight() == that.weight())
return 0;
else
return 1;
}
std::string to_string()
{
char str[20];
sprintf_s(str,20 ,"%d-%d %.2f\n", v, w, wei);
std::string s(str);
return s;
}
};
带权图的构造
/*带权图*/
class EWgraph
{
private:
int v;
int e;
std::vector<std::vector<edge>> adj;
public:
EWgraph(int v)
{
this->v = v;
this->e = 0;
adj.resize(v);
}
int numv()
{
return v;
}
int nume()
{
return e;
}
void add_edge(edge e)
{
int v = e.either();
int w = e.other(v);
adj[v].push_back(e);
adj[w].push_back(e);
this->e++;
}
std::vector<edge> iterator(int v)
{
return adj[v];
}
std::vector<edge> edges() //返回所有边
{
std::vector<edge> v;
for (int i = 0; i < this->v; i++)
{
for (auto e : adj[i])
{
if(e.other(i) > i)
{
v.push_back(e);
}
}
}
return v;
}
};
其实我从不太习惯用这种方式来构造带权图,我更喜欢使用二维数组构建一个邻接矩阵来表示带权图。虽然这种方法可能回浪费大量的空间,但是在速度上可能会比大量的使用类更快。当然我们C/C++程序员可能天生不如JAVA程序员那么喜欢面向对象
kruskal
基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路,即保证属于同一连通分支的两点之间的路径不会被选择
bool ewcmp(edge a, edge b)
{
return a.cmpt(b) < 0;
}
std::vector<edge> kruskal(EWgraph g)
{
std::vector<edge> mst;
std::vector<edge> all = g.edges();
union_find color(g.numv());
std::sort(all.begin(), all.end(), ewcmp);
for (auto i : all)
{
int v = i.either();
int w = i.other(v);
if (color.connected(v, w))
{
continue;
}
color.uf(v, w);
mst.push_back(i);
if (mst.size() >= g.numv()- 1)
break;
}
return mst;
}
用到了第一章中出现的union-find算法