哦,要开始码字了,有点紧张,又有点兴奋,好啦,废话不多说,开始吧。
1.dfs
dfs,中文名称深度优先搜索,从顶点V开始,访问这个顶点,然后依次从V的未被访问的邻接点出发深度优先遍历图,直至图中所有和V有路径的相通的顶点都被访问了,如果此时还有顶点未被访问,则选择图中未被访问的那个顶点作为起点,重复上述动作。emmm,上面这句我直接超的。好吧,现在来解释一下把。(以下文字内容为本博主自己的见解,如果有误,请提醒我,不许指出哦)
(图片来源:https://lemon2013.github.io/2017/05/27/graph-search/)
A.无向图(根据字母顺序选取结点)
以A为初始点,记录点A为已访问,A的后续结点为B,E,选择结点B,记录点B为已访问,B的后续节点为C,D,E,选择结点C,记录点C为已访问结点,C的后续结点为D,选择结点D,记录结点D为已访问结点,D的后续节点为E,选择结点E,记录结点E为已访问结点,E无后续节点,回溯到点D,点D无后续结点,回溯到点C,点C无后续结点,回溯到B点,点B后续节点还有D,E,点D和点E皆为已访问结点,所以回溯到点A,点A后续结点还剩点E,点E已访问,所以dfs结束。
B.有向图(根据字母顺序选取结点)
以A为初始点,记录A已访问,A的后续节点为B,D,选择结点B,记录点B为已访问,B的后续节点为C,D,选择结点C,记录结点C为已访问结点,点C后续结点为E,选择结点E,记录结点E为已访问结点,结点E无后续节点,回溯到点C,点C无其他后续结点,回溯到点B,点B还有一个未访问后续节点为D,选择点D,记点D为已访问结点,点D后续节点均被访问,回溯到点B,点B无后续结点,回溯到点A,点A无后续结点,dfs结束。
有向图和无向图的dfs都一个样,主要注意的是遍历的顺序和条件。
2.bfs
bfs,中文名称为广度优先搜索,它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名。不多说,上图!
A.无向图
以A为初始点,A进栈,记录点A为已访问,A出栈,A的相邻节点为B,E。 B,E入栈,记录结点B已访问,B相邻结点为C与D。B出栈,C,D入栈,E相邻结点以入栈,记录点E为已访问,E出栈,C相邻结点以入栈,记录C为已访问,C出栈,记录D为已访问,D出栈。
A进栈--BE进栈--A出栈--CD进栈--B出栈--E出栈--C出栈--D出栈
B.有向图
以A为初始点,A进栈,记录点A为已访问,A的后续结点为B,D。BD入栈,记录B为已访问,B的后续结点为C,C进栈,B出栈,记录D为已访问,D的后续结点为E,E入栈,D出栈,记录点C为已访问,C出栈,记录点E位于服务,E出栈。
A进栈--BD进栈--A出栈--C进栈--B出栈--E进栈--D出栈--C出栈--E出栈
3.单源最短路
单源最短路呢,意思就是从一个点到其他所有点的最短边权。
(1)Dijkstra(其他的以后总结)
Dijkstra算法采用贪心策略:按路径长度递增的顺序,逐个产生各顶点的最短路径。算法过程中需要维护一个顶点集,此顶点集保存已经找到最短路径的顶点。还需要维护一个距离数组dist, dist[i]表示第i个顶点与源结点s的距离长度。
问题:求1到其余4点的最短路径值?(例题来源:https://blog.csdn.net/jiahui524/article/details/6636913)
初始:S中只有1这个点,dist[2]~dst[5]中最短距离为10,最大为INF;
第一次:选择最短距离的点2,加入S,更新1到其余点的距离,dist[3] = dist[2] + a[2][3] = 60;
第二次:选择最短距离的点4,加入S,更新1到其余点的距离,dist[5] = dist[4] + a[4][5] = 90, dist[3] = dist[4] + a[4][3] = 50;
第三次:选择最短距离的点3,加入S,更新1到其余点的距离,dist[5] = dist[3] + a[3][5] = 60;
第四次:选择最短距离的点5,加入S,更新1到其余点的距离;
int dijkstra(int s,int t) { 初始化S={空集} d[s] = 0; 其余d值为正无穷大 while (NOT t in S) { 取出不在S中的最小的d[i]; for (所有不在S中且与i相邻的点j) if (d[j] > d[i] + cost[i][j]) d[j] = d[i] + cost[i][j]; ( “松弛”操作” ) S = S + {i}; //把i点添加到集合S里 } return d[t]; }
代码实现:(1到5的最短路径(dist[5]))
#include <iostream> using namespace std; #define MAX 9999999 #define LEN 210 int map[LEN][LEN]; //某点到某点两点间的的距离 int dist[LEN]; //记录当前点到源点的最短路径长度 int mark[LEN]; //加入进来的点的集合 //初始化map为正无穷大 void init(){ int i,j; for(i=0;i<LEN;i++){ for(j=0;j<LEN;j++){ map[i][j]=MAX; } } } //n:多少条路 start:起始点 void myDijstra(int n,int start){ int i,j,min,k; for(i=1;i<=n;i++){ mark[i]=0;//没有点加入 dist[i]=map[start][i];//初始 } mark[start]=1;//把起始点加进来 dist[start]=0; for(i=1;i<=n;i++){ min=MAX; for(j=1;j<=n;j++){ if(!mark[j] && dist[j]<min){ //取出不在mark里的最小的dist[i] min=dist[j]; k=j;//标记 } } if(min==MAX) break; mark[k]=1;//把K加进来 //做松弛操作 for(j=1;j<=n;j++){ if(!mark[j] && dist[j]>dist[k]+map[k][j]){ dist[j]=dist[k]+map[k][j]; } } } } int main(){ int i,j,n,line; int a,b,d; cin>>n>>line; //输入点和边 init(); for(i=0;i<line;i++){ cin>>a>>b>>d; //输入各边的权值 if(map[a][b]>d){ map[a][b]=map[b][a]=d; } } myDijstra(n,1);//调用方法 //输出1到5的最短路径 cout<<dist[5]<<endl; return 0; }
4.多源最短路
(1)floyd
多源最短路就是指每一个点到图中其他顶点的最短路。
代码模板:
int g[N][N]; void floyd(int n) { for (int k = 1; k <= n; ++k) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { g[i][j] = min(g[i][j], g[i][k] + g[k][j]); } } } }