最小生成树 最短路 并查集

来源:互联网 发布:java 闰年 编辑:程序博客网 时间:2024/05/17 04:36

Dijkstra单源最短路算法,即计算从起点出发到每个点的最短路

使用邻接矩阵的时间复杂度为O(n^2)

算法思想过程和图论与集合一门课中所学的一样

void dijkstra(int s)//从s点到其余点的最短路{    memset(vis,0,sizeof(vis));           int cur=s;                       dis[cur]=0;    vis[cur]=1;    for(int i=0;i<n;i++)    {        for(int j=0;j<n;j++)                                 if(!vis[j] && dis[cur] + map[cur][j] < dis[j])   //未被标记且比已知的短,可更新                dis[j]=dis[cur] + map[cur][j] ;         int mini=INF;        for(int j=0;j<n;j++)                              if(!vis[j] && dis[j] < mini)    //选择下一次到已知顶点最短的点                mini=dis[j];cur=j;        vis[cur]=true;    }   }

求最小生成树:prim算法     其原理和 dijstra算法差不多,更新的地方有些不一样。

dis[i] = min(dis[i], maze[mark][i]);

prim算法的代码实现如下

int maze[maxn][maxn];//存图int dis[maxn];//存最小边bool vis[maxn];//是否连接int ans;//求和void prim(){       dis[1] =0; //起点置为1    for(int i=1; i<=n; i++)    {        int minn = INF;//临时最短路        int mark;        for(int j=1; j<=n; j++)//找所有距离中最短的        {            if(!vis[j] && dis[j]<minn)            {                minn = dis[j];                mark = j;            }        }        vis[mark] = true;        ans += dis[mark];        for(int j=1; j<=n; j++)//将dis数组更新成最新树中与剩余点的最短路        {//如果,顶点i未被访问过//且图中新加入的pos点到i点的距离短于原来图到i点的距离//且pos到i的点有连通(即不为无穷大),则将i点到图的距离更新.             if(!vis[j] && dis[j]>maze[mark][j])                dis[j] = maze[mark][j];        }    }    printf("%d\n",ans);}

初始化函数

void init(){    memset(maze, INF, sizeof(maze));    memset(dis, INF, sizeof(dis));    memset(vis, false, sizeof(vis));    ans = 0;}


floyd算法用于求所有点对的距离 时间复杂度为O(n^3)

void floyd()  {      for(int k=0;k<n;k++)          for(int i=0;i<n;i++)              for(int j=0;j<n;j++)                  dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);  }

并查集算法

算法思想什么的来自这儿  并查集算法

#define N 100// 初始化并查集int father[N];void init() {    for(int i=0; i<N; i++)      father[i] = i;}// 合并两个元素所在的集合void union(int x,int y) {    x = getfather(x);    y = getfather(y);    if(x!= y)       father[x]=y;}// 判断两个元素是否属于同一个集合bool same(int x,int y) {    return getfather(x)==getfather(y);}// 获取根结点  1int getfather(int x) {    while(x != father[x])      x = father[x];    return x;}// 获取根结点  2int getfather(int x) {    if(x != father[x])      father[x] = getfather(father[x]); // 路径压缩修改的是father数组    return father[x];}
例题   杭电1232 畅通工程

int maze[maxn][maxn];//存图int dis[maxn];//存最小边bool vis[maxn];//是否连接int ans;//求和void prim(){       dis[1] =0; //起点置为1    for(int i=1; i<=n; i++)    {        int minn = INF;//临时最短路        int mark;        for(int j=1; j<=n; j++)//找所有距离中最短的        {            if(!vis[j] && dis[j]<minn)            {                minn = dis[j];                mark = j;            }        }        vis[mark] = true;        ans += dis[mark];        for(int j=1; j<=n; j++)//将dis数组更新成最新树中与剩余点的最短路        {//如果,顶点i未被访问过//且图中新加入的pos点到i点的距离短于原来图到i点的距离//且pos到i的点有连通(即不为无穷大),则将i点到图的距离更新.             if(!vis[j] && dis[j]>maze[mark][j])                dis[j] = maze[mark][j];        }    }    printf("%d\n",ans);}
0 0
原创粉丝点击