//头文件省略
struct Edge
{
int from, to, val;
Edge(int f = 0, int t = 0, int v = 0) : from(f), to(t), val(v) {}
};
struct Graph
{
vector<vector<int>> graph;//邻接表
vector<vector<int>> weights;//邻接矩阵
vector<Edge> edges; //边集
int p_num;
Graph(int point_num) : p_num(point_num), graph(point_num + 1, vector<int>(0)),
weights(point_num + 1, vector<int>(point_num + 1, -1)), edges(0) {
for(int i = 1; i <= point_num; ++i)
weights[i][i] = 0;
}
//from to 从1开始
void add_dege(int from, int to, int weight)
{
graph[from].push_back(to);
weights[from][to] = weight;
edges.push_back(Edge(from, to, weight));
}
//并查集
struct Union_find_set
{
vector<int> fa;
int find(int x)
{
if(x != fa[x])
fa[x] = find(fa[x]);
return fa[x];
}
void unionn(int x, int y)
{
int fx = find(x), fy = find(y);
fa[fx] = fy;
}
Union_find_set(int n) : fa(n + 1)
{
for(int i = 1; i <= n; ++i)
fa[i] = i;
}
};
//Minimum Spanning Tree最小生成树,洛谷p3366通过
int MST_Kruskal()
{
int ret = 0;
vector<bool> vis(p_num + 1, false);
sort(edges.begin(), edges.end(), [](Edge &e1, Edge &e2) {return e1.val < e2.val; } );
Union_find_set st(p_num);
for(auto &e : edges) //对每个边,检查两个点是否是一个连通块
{
int a = st.find(e.from), b = st.find(e.to);
if( a != b) //不是一个连通块,返回值加上权重
{
st.unionn(a, b);
ret += e.val;
}
}
//如果图不连通
for(int i = 1; i < p_num; ++i)
if(st.find(i) != st.find(i+1))
return -1;
return ret;
}
//Minimum Spanning Tree最小生成树,洛谷p3366通过,注意重边
int MST_Prim()
{
int ret = 0;
struct dis {
int x, val;
dis(int x, int v) : x(x), val(v) {}
bool operator < (const dis &d) const {return d.val < val; }
};
priority_queue<dis> q;
vector<bool> vis(p_num + 1, false);
vis[0] = true;
q.push(dis(1, 0));
while(!q.empty())
{
dis d = q.top(); q.pop();
if(vis[d.x]) continue;
vis[d.x] = true;
ret += d.val;
for(auto &a : graph[d.x])
{
if(vis[a] == false)
q.push(dis(a, weights[d.x][a]));
}
}
for(auto a : vis)
if(a == false)
return -1;
return ret;
}
//多源最短路,leetcode 743通过
vector<vector<int>> Floyd()
{
vector<vector<int>> dis = weights;
for(int k = 1; k <= p_num; ++k)
for(int i = 1; i <= p_num; ++i)
{
if(dis[i][k] == -1)
continue;
for(int j = 1; j <= p_num; ++j)
{
if(dis[k][j] == -1)
continue;
if(dis[i][j] == -1 || dis[i][k] + dis[k][j] < dis[i][j])
dis[i][j] = dis[i][k] + dis[k][j];
}
}
return dis;
}
//单源最短路,leetcode 743通过
vector<int> Dijkstra(int start)
{
vector<bool> vis(p_num + 1, false);
vector<int> dis(p_num + 1, 0x7fffffff);
dis[start] = 0;
struct node
{
int x, val;
node(int x, int val) : x(x), val(val) {}
bool operator < (const node &n) const {return n.val < val; }
};
priority_queue<node> q;
q.push({start, 0});
while(!q.empty())
{
node n = q.top(); q.pop();
if(vis[n.x]) continue;
vis[n.x] = true;
for(auto &y : graph[n.x])
{
if(dis[n.x] + weights[n.x][y] < dis[y])
{
dis[y] = dis[n.x] + weights[n.x][y];
q.push({y, dis[y]});
}
}
}
return dis;
}
};