稠密图(邻接矩阵),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)
全部函数通过杭电 1142,1162,1198,1213等题目测试。
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
using namespace std; /*
//函数集合声明下,方便查看
void Dijkstra(const denseGraph& dg, int s);
void spfa(const denseGraph& dg, int s);
weightType prim(const denseGraph& dg, int s);
void makeSet(int x);
int findSet(int x);
void unionSet(int x, int y);
weightType kruskal(const denseGraph& dg);
*/ //稠密图,邻接矩阵表示
#define N 1000 //表示顶点数最大值
#define NOEDGE 1000000 //表示无边,用于距离类求解中
typedef double weightType; //表示带边权的类型
//定义带权边类
struct edge{
int v, w;
weightType val;
edge(int v = -, int w = -, weightType val = NOEDGE) :v(v), w(w), val(val){}
};
//定义稠密图类
struct denseGraph{
int Vcnt, Ecnt; //顶点数,边数
bool dg; //有向图 ?
vector< vector<weightType> > adj; //邻接矩阵
denseGraph(int v, bool dg = false) :adj(v), Vcnt(v), Ecnt(), dg(dg){
for (int i = ; i < v; ++i)
adj[i].assign(v, NOEDGE);
}
void insert(edge e){
int v = e.v, w = e.w;
weightType val = e.val;
if (adj[v][w] == NOEDGE) ++Ecnt;
adj[v][w] = val;
if (!dg) adj[w][v] = val;
}
void show(){
printf("Vcnt = %d, Ecnt = %d, Directed : %d\n", Vcnt, Ecnt, dg);
for (int i = ; i < Vcnt; ++i){
for (int j = ; j < Vcnt-; ++j)
cout << adj[i][j] << ' ';
cout << adj[i][Vcnt - ] << endl;
}
}
}; //Dijkstra算法
weightType dDijkstra[N]; //存放所有顶点到 s 的最短路径距离
int pDijkstra[N]; //pDijkstra[i],路径存在时,存放节点 i 的前驱,不存在时,-1
void Dijkstra(const denseGraph &dg, int s)
{
bool visit[N]; //集合 S ,visit[i]=true, i 属于集合 S
for (int i = ; i < dg.Vcnt; ++i){ //初始化
visit[i] = false;
dDijkstra[i] = dg.adj[s][i];
pDijkstra[i] = dDijkstra[i] == NOEDGE ? - : s;
}
visit[s] = true; dDijkstra[s] = ;
for (int i = ; i < dg.Vcnt - ; ++i){ //dg.Vcnt-1次选点
int min = NOEDGE;
int v = ;
for (int j = ; j < dg.Vcnt; ++j){ //选距离最近点
if (!visit[j] && dDijkstra[j] < min){
v = j; min = dDijkstra[j];
}
}
visit[v] = true;
for (int j = ; j < dg.Vcnt; ++j){ //更新与 v 直接相连的顶点
if (!visit[j] && min + dg.adj[v][j] < dDijkstra[j]){
dDijkstra[j] = min + dg.adj[v][j];
pDijkstra[j] = v;
}
} }
} //最短路径 SPFA算法
weightType dSpfa[N];
int pSpfa[N];
void spfa(const denseGraph& dg, int s)
{
bool visit[N];
for (int i = ; i < dg.Vcnt; ++i){
visit[i] = false;
dSpfa[i] = NOEDGE;
pSpfa[i] = -;
}
dSpfa[s] = ;
int u;
queue<int> q;
q.push(s);
while (!q.empty()){
u = q.front(); q.pop();
for (int i = ; i < dg.Vcnt; ++i){
if (dSpfa[u] + dg.adj[u][i] < dSpfa[i]){
dSpfa[i] = dSpfa[u] + dg.adj[u][i];
pSpfa[i] = u;
if (!visit[i])
q.push(i);
}
}
}
} //最小生成树 prim
weightType dPrim[N]; //存放所有顶点到 s 的最短路径距离
weightType prim(const denseGraph& dg, int s)
{
weightType sum = ;
bool visit[N];
for (int i = ; i < dg.Vcnt; ++i){ //初始化
visit[i] = false;
dPrim[i] = dg.adj[s][i];
}
visit[s] = true; dPrim[s] = ;
for (int i = ; i < dg.Vcnt - ; ++i){
weightType min = NOEDGE;
int v = ;
for (int j = ; j < dg.Vcnt; ++j){ //选点
if (!visit[j] && dPrim[j] < min){
v = j; min = dPrim[j];
}
}
sum += min;
visit[v] = true;
for (int j = ; j < dg.Vcnt; ++j){
if (!visit[j] && dg.adj[v][j] < dPrim[j]){
dPrim[j] = dg.adj[v][j];
}
}
}
return sum;
} //并查集实现,点集[0,1,2,3,4,...,n-1]
int parentSet[N];
int rankSet[N];
void makeSet(int x)
{
parentSet[x] = x;
rankSet[x] = ;
}
void linkSet(int x, int y)
{
if (rankSet[x] > rankSet[y])
parentSet[y] = x;
else {
parentSet[x] = y;
if (rankSet[x] == rankSet[y])
++rankSet[y];
}
}
int findSet(int x)
{
vector<int> v;
while (parentSet[x] != x){
v.push_back(x);
x = parentSet[x];
}
for (int i = ; i < v.size(); ++i)
parentSet[v[i]] = x;
return x;
}
void unionSet(int x, int y)
{
linkSet(findSet(x), findSet(y));
} //最小生成树 kruskal
bool kruskalComp(const edge& a, const edge& b)
{
return a.val < b.val;
}
weightType kruskal(const denseGraph& dg)
{
weightType sum = ;
edge e;
vector<edge> ve;
for (int i = ; i < dg.Vcnt; ++i)
for (int j = ; j <= i; ++j)
if (dg.adj[i][j]!=NOEDGE)
ve.push_back(edge(i, j, dg.adj[i][j]));
if (dg.dg){
for (int i = ; i < dg.Vcnt; ++i)
for (int j = i + ; j < dg.Vcnt; ++j)
if(dg.adj[i][j]!=NOEDGE)
ve.push_back(edge(i, j, dg.adj[i][j]));
}
sort(ve.begin(), ve.end(), kruskalComp); for (int i = ; i < dg.Vcnt; ++i)
makeSet(i); for (int i = ; i < ve.size(); ++i){
e = ve[i];
int x = findSet(e.v);
int y = findSet(e.w);
if (x != y){
unionSet(x, y);
sum += e.val;
}
}
return sum;
} /*测试数据
5 6
1 3 2
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24 7 8
1 3 1
1 4 1
3 7 1
7 4 1
7 5 1
6 7 1
5 2 1
6 2 1
*/
int main()
{
int v, w, val, n, m;
cin >> n >> m;
denseGraph dg(n,true);
while (m--){
cin >> v >> w >> val;
dg.insert(edge(v - , w - , val));
}
dg.show();
cout << endl;
for (int i = ; i < dg.Vcnt; ++i){
spfa(dg, i);
Dijkstra(dg, i);
for (int i = ; i < dg.Vcnt; ++i)
cout << dSpfa[i] << ' ';
cout << endl;
for (int i = ; i < dg.Vcnt; ++i)
cout << dDijkstra[i] << ' ';
cout << endl; for (int i = ; i < dg.Vcnt; ++i)
cout << pSpfa[i] << ' ';
cout << endl;
for (int i = ; i < dg.Vcnt; ++i)
cout << pDijkstra[i] << ' ';
cout << endl << endl; } for (int i = ; i < dg.Vcnt; ++i)
cout << prim(dg, i) << endl;
cout << kruskal(dg) << endl;
}
稠密图(邻接矩阵),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)的更多相关文章
- 几个小模板:topology, dijkstra, spfa, floyd, kruskal, prim
1.topology: #include <fstream> #include <iostream> #include <algorithm> #include & ...
- 2019 蓝桥杯国赛 B 组模拟赛 E 蒜头图 (并查集判环)
思路: 我们看条件,发现满足条件的子图无非就是一些环构成的图, 因为只有形成环,才满足边的两个点都在子图中,并且子图中节点的度是大于0的偶数. 那么如果当前有k个环,我们可以选2^k-1个子图,为什么 ...
- 图-连通分量-DFS-并查集-695. 岛屿的最大面积
2020-03-15 16:41:45 问题描述: 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二 ...
- 洛谷P4768 [NOI2018]归程 [可持久化并查集,Dijkstra]
题目传送门 归程 格式难调,题面就不放了. 分析: 之前同步赛的时候反正就一脸懵逼,然后场场暴力大战,现在呢,还是不会$Kruskal$重构树,于是就拿可持久化并查集做. 但是之前做可持久化并查集的时 ...
- 二分图建图,并查集求联通——二维等价性传递 cf1012B好题!
/* 模拟二分图:每个点作为一条边,连接的是一列和一行(抽象成一个点,列在左,行在右) 由题意得 a-b相连,a-c相连,b-d相连,那么d-c就不用再相连了 等价于把二分图变成联通的需要再加多少边 ...
- [数据结构与算法-15]单源最短路径(Dijkstra+SPFA)
单源最短路径 问题描述 分别求出从起点到其他所有点的最短路径,这次主要介绍两种算法,Dijkstra和SPFA.若无负权优先Dijkstra算法,存在负权选择SPFA算法. Dijkstra算法 非负 ...
- 九度OJ 1024 畅通工程 -- 并查集、贪心算法(最小生成树)
题目地址:http://ac.jobdu.com/problem.php?pid=1024 题目描述: 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但 ...
- fzu 2087并查集的运用求最小生成树的等效边
//对数组排序后,对于边相同并且边的两端不在一个集合内的一定是等效边或者必加边, //第一数数,第二合并集合 #include<stdio.h> #include<stdlib.h& ...
- PAT Advanced A1021 Deepest Root (25) [图的遍历,DFS,计算连通分量的个数,BFS,并查集]
题目 A graph which is connected and acyclic can be considered a tree. The height of the tree depends o ...
- PAT Advanced 1034 Head of a Gang (30) [图的遍历,BFS,DFS,并查集]
题目 One way that the police finds the head of a gang is to check people's phone calls. If there is a ...
随机推荐
- 类 的继承性(Inherits)与 重写(Overrides)
(类) 与 (结构) 类似,让我们可以定义并封装成一组相关项的数据类型.比如封装成结构,那么这个封装包的数据类型就为值类型:如封装成类,那么这个封装包的数据类型就为引用类型. 然而与结构的一个重要区别 ...
- 发现一个不错的学习git的地方
Git入门:http://rogerdudler.github.io/git-guide/index.zh.html 简洁.实用.高效的学习git基本操作的方式
- onbeforepaste
onbeforepaste事件用法 onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').rep ...
- MySQL数据库主从同步安装与配置总结
MySQL的主从同步是一个很成熟的架构,优点为: ①在从服务器可以执行查询工作(即我们常说的读功能),降低主服务器压力: ②在从主服务器进行备份,避免备份期间影响主服务器服务: ③当主服务器出现问题时 ...
- Python之路第十天,高级(2)-多线程,多进程,协程
线程 threading threading模块对象 描述 Thread 表示一个线程的执行对象 Lock 锁原语对象 RLock 可重入锁对象,使单线程可再次获得已经获得了的锁(递归锁定) Cond ...
- Asp.net MVC4 下二级联动
效果图:
- Matlab 仿真实现TI Instaspin 的Foc 逆Clarke变换和SVPWM
一直没搞明白TI 的Instaspin的SVPWM实现原理,最后只能在Matlab里仿真看看输出波形是不是和普通的SVPWM实现输出的波形一样,用M文件实现,下面是代码: clear all; the ...
- 安全运维之:Linux系统账户和登录安全(转)
三.删减系统登录欢迎信息 系统的一些欢迎信息或版本信息,虽然能给系统管理者带来一定的方便,但是这些信息有时候可能被黑客利用,成为攻击服务器的帮凶,为了保证系统的安全,可以修改或删除某些系统文件,需要修 ...
- linux 用户空间获得纳秒级时间ns
一.引言 我们在测试程序的性能的时候往往需要获得ns级的精确时间去衡量一个程序的性能,下面介绍下linux中用户空间获得ns级时间的方法 二.用户空间获得ns级时间 使用clock_gettime函数 ...
- java 科学计数法表示转换
BigDecimal strScien = new BigDecimal("9.67953970412123E-05"); System.out.println(strScien. ...