以前用邻接表实现的图算法程序写得有点复杂,无法立刻看懂,重新用邻接矩阵写得简单点,某年某月能一看就回忆起该算法。
广度优先算法(Breadth-First-Search),又称作宽度优先搜索,或横向优先搜索,简称BFS,是一种图形搜索演算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点,如果发现目标,则演算终止。广度优先搜索的实现一般采用open-closed表。
#include
#include
#include
#include
#include
using namespace std;
#define vertex_nums 8
bool BFS(vector> &graph , vector &path,int start_vertex);//广度优先遍历要快速想到队列
int _tmain(int argc, _TCHAR* argv[])
{
system("color 0A");
//初始化图
vector row(vertex_nums, -1);
vector> graph(vertex_nums, row);
for (int i = 0; i bfs_path(vertex_nums, -1);
int s_v = 2, e_v = 7;
BFS(graph, bfs_path, s_v);
system("pause");
return 0;
}
//广度优先检查图
//时间复杂度O(v^2)
//连接表的速度是O(v+e),对于稀疏图而言,邻接表更有优势!
bool BFS(vector> &graph, vector &bfs_path, int start_vertex)
{
vector visited(vertex_nums,0);
visited[start_vertex] = 1;
queue que;
que.push(start_vertex);
//用于记录路径
int idx = 0;
bfs_path[idx++]=start_vertex;
while (!que.empty())
{
int cur_ver = que.front();
que.pop();
//广度搜索当前节点的相邻节点
for (int i = 0; i < vertex_nums; i++)
{
if (graph[cur_ver][i] > 0 && visited[i] == 0)
{
visited[i] = 1;
bfs_path[idx++] = i;
que.push(i);
}
}
}
return true;
}
深度优先搜索算法(Depth-First-Search),是搜索算法的一种。是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define vertex_nums 8
bool DFS(vector> &graph, vector &path, vector &visited, int &idx, int start_vertex);
int _tmain(int argc, _TCHAR* argv[])
{
system("color 0A");
//初始化图
vector row(vertex_nums, -1);
vector> graph(vertex_nums, row);
for (int i = 0; i dfs_path(vertex_nums, -1);
vector visited(vertex_nums, 0);
int s_v = 2, e_v = 7;
int idx = 0;
visited[s_v] = 1;
DFS(graph, dfs_path, visited,idx, s_v);
getchar();
return 0;
}
//深度优先检查图
//时间复杂度O(v^2)
//连接表的速度是O(v+e),对于稀疏图而言,邻接表更有优势!
bool DFS(vector> &graph, vector &dfs_path, vector &visited , int &idx, int start_vertex)
{
dfs_path[idx++] = start_vertex;
for (int i = 0; i < vertex_nums; i++)
{
if (graph[start_vertex][i] > 0 && visited[i] == 0)
{
visited[i] = 1;
DFS(graph,dfs_path,visited,idx,i);
}
}
return true;
}
始终记住最短路径算法的核心内容,每次迭代始终在更新shortpath中的最短路径值:
贪心的最短路径:shortpath[j]=min{shortpath[j],shortpath[i]+graph[i][j]}
shortpath[j]始终存放起点到j的当前最短路径,i为当前中心点
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define vertex_nums 8
int dijkstra(vector> &graph, int start_vertex, int end_vertex, vector &path);
int _tmain(int argc, _TCHAR* argv[])
{
system("color 0A");
//初始化图
vector row(vertex_nums, INT_MAX);
vector> graph(vertex_nums, row);
for (int i = 0; i path(vertex_nums, -1);
int resukt = dijkstra(graph, 2, 7, path);
for (int k = 7; path[k] != -1; k = path[k])
cout << k << " ";
cout << 2;
getchar();
return 0;
}
//最短路径:shortpath[j]=min{shortpath[j],shortpath[i]+graph[i][j]}
//shortpath[j]始终存放起点到j的当前最短路径
int dijkstra(vector> &graph, int start_vertex, int end_vertex, vector &path)
{
vector shortpath(vertex_nums, INT_MAX);//存储起点到各点的最短路径
vector visited(vertex_nums, 0);//已访问过的顶点
for (int i = 0; i < vertex_nums; i++)//初始化当前原点到其他店的距离,如果不相连则为INT_MAX
{
if (graph[start_vertex][i] != INT_MAX)
shortpath[i] = graph[start_vertex][i];
}
visited[start_vertex] = 1;//起点初始化为被访问,并以他为当前中心点开始找最短路径
int min_weight = INT_MAX;
int u = -1;
int nums = vertex_nums - 1;
bool first = true;
while (nums)
{
min_weight = INT_MAX;
u = -1;
for (int i = 0; i < vertex_nums; i++)
{
if (visited[i] == 0 && shortpath[i] < min_weight)
{
u = i;
min_weight = shortpath[i];
}
}
if (first)
{
path[u] = start_vertex;//更新记录前驱顶点,供最后回溯最短路径
first = false;
}
visited[u] = 1;//已经确定起点到u的最短路径
nums--;
if (end_vertex == u)//如果u就是终点的话,就不用再找了!
break;
//以u为中间点寻找起点到顶点w的最短路径
for (int w = 0; w < vertex_nums; w++)
{
if (visited[w] == 0 && graph[u][w] != INT_MAX && min_weight + graph[u][w] < shortpath[w])
{
shortpath[w] = min_weight + graph[u][w];//更新起点到w的最短路径值
path[w] = u;//更新记录前驱顶点,供最后回溯最短路径
}
}
}
return shortpath[end_vertex];
}
Prim算法是以图的顶点起始点,每次选取所有顶点上对应的权值最小的边进行构建,所以prim的时间开销和边无关,对于定点数为n时Prim的时间复杂度为 O(n^2),所以prim算法更适合求解边数很多的稠密图的MST。
具体步骤:将整个顶点集合分为两个子集U、V,U中存放已经在生成树中的顶点,V中存放未在生成树中的顶点。算法核心的每一步将从U、V中各选一顶点,并且边的权值w(u,v)是最小的,然后将该顶点v从V中移到U中,如此直到集合V为空,即完成。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define vertex_nums 8
int Prim(vector> &graph);
int _tmain(int argc, _TCHAR* argv[])
{
system("color 0A");
//初始化图
vector row(vertex_nums, INT_MAX);
vector> graph(vertex_nums, row);
for (int i = 0; i1,1就是目的顶点)
int Prim(vector> &graph)
{
int sum = 0;
int u = 0;//起点
vector lowcost(vertex_nums, 0);
vector closest(vertex_nums,0);
vector visited(vertex_nums,false);
for (int i = 0; i < vertex_nums; i++)
lowcost[i] = graph[u][i];//start_ver为起点
visited[u] = true;
for (int i = 1; i < vertex_nums; i++)
{
int min = INT_MAX;
u = -1;
//寻找未被加入mst的最小权值边
for (int k = 0; k < vertex_nums; k++)
{
if ((lowcost[k] < min) && visited[k] == false)
{
min = lowcost[k];
u = k;
}
}
if (u == -1)//不是连通图
return -1;
cout << closest[u] << "--->" << u << endl;//输出最小生成树的连接情况路径。
sum += min;
visited[u] = true;
//更新当前节点u到其他节点的权值
for (int k = 0; k < vertex_nums; k++)
{
if ((graph[u][k] < lowcost[k]) && visited[k] == false)
{
lowcost[k] = graph[u][k];
closest[k] = u;
}
}
}
return sum;
}
秒杀该算法:
该问题就是最小生成树问题:练习3,还是畅通工程
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
对每个测试用例,在1行里输出最小的公路总长度。
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
3
5
#include "vector"
#include "string"
#include "algorithm"
#include
#include "stack"
#include
#include
using namespace std;
class Edge
{
public:
int acity;//城市a
int bcity;//城市b
int cost; //建成a到b的路的花费
bool operator < (const Edge &q) const//注意返回值的类型,运算符重载。
{
return cost> n, n > 0)
{
int m = n*(n - 1) / 2;
UFSet uset(100);
uset.makeSet(n);//初始化每个城市的祖先为自身
for (int i = 0; i < m; i++)
cin >> edge[i].acity >> edge[i].bcity >> edge[i].cost;
int mincost = uset.getMinCost(m);
cout << mincost << endl;
}
return 0;
}
/**************************************************************
Problem: 1017
User: EbowTang
Language: C++
Result: Accepted
Time:30 ms
Memory:1636 kb
****************************************************************/