图论

1 最小生成树

1.1 Kruskal算法

选n-1条边

  1. 初始化:建立一个边的数组,并根据权值排序。
  2. 选边:选择权值最小的,且两端点不在同一集合(回路)的边。
  3. 重复2,直到所有边遍历完。

核心代码

int kruskal(vector e) {
    makeSet();
    int sum = 0;
    for (int i = 0; i

主函数调用:定义edge类,生成edge的数组,并排序

#include
#include
#include
#define INF 10000
using namespace std;

//定义一个edge类
class edge {
public:
    int val;
    int start;
    int end;

    edge(int v, int x, int y) {
        val = v;
        start = x;
        end = y;
    }
};

bool cmp(edge a, edge b) {
    return a.val < b.val;
}

//图
const int N = 6;
int graph[N][N] = { { INF,7,4,INF,INF,INF },  
{ 7,INF,6,2,INF,4 },
{ 4,6,INF,INF,9,8 },
{ INF,2,INF,INF,INF,7 },
{ INF,INF,9,INF,INF,1 },
{ INF,4,8,7,1,INF }
};

int main() {
    //遍历图,生成边的集合
    vector e; 
    for (int i = 0; i

并查集的实现

//并查集
int father[N]; 

void makeSet() {
    for (int i = 0; i

1.2 Prim算法

选n个点

  1. 初始化:任意选一点作为初始顶点,标记为visit(加入集合),剩下的点与该点的距离作为到该集合的初始化距离。
  2. 加入新点:剩下点中,到该集合最近的点index加入到集合中。
  3. 更新距离:剩下点到该集合的距离d[j]=min(d[ij],graph[j][index])。
  4. 重复2,3步骤n-1次,即所有节点都加入到集合中。


    图论_第1张图片

    核心代码

int prim(int cur)
{
    //1.初始化
    int sum = 0; //路径和
    cout << cur << " ";
    visit[cur] = true;
    for (int i = 0; i < N; i++)
        dist[i] = graph[cur][i]; 

    for (int i = 1; i < N; i++) //4.重复取点n-1次
    {
        //2.选点
        int minTemp = INF, index = -1;
        for (int j = 0; j < N; j++)
        {
            if (!visit[j] && dist[j] < minTemp)
            {
                minTemp = dist[j];
                index = j;
            }
        }
        visit[index] = true;
        cout << index << " ";
        sum += minTemp;
        //3.更新距离
        for (int j = 0; j < N; j++)
        {
            if (!visit[j])
            {
                dist[j] = min(dist[j], graph[index][j]);
            }
        }
    }
    cout << endl;
    return sum;
}

主函数调用

#include
#include
#include
#define INF 10000
using namespace std;

const int N = 6; //顶点数
vector visit(N,false);  //每个顶点加入集合的标记
vector dist(N,0); //剩下顶点到集合的距离
int graph[N][N] = { { INF,7,4,INF,INF,INF },  //INF代表两点之间不可达
{ 7,INF,6,2,INF,4 },
{ 4,6,INF,INF,9,8 },
{ INF,2,INF,INF,INF,7 },
{ INF,INF,9,INF,INF,1 },
{ INF,4,8,7,1,INF }
};

int main()
{
    int sum = prim(0);//从0号顶点出发
    cout << sum;
    system("pause");
    return 0;
}

2 最短路径

2.1 Floyd算法

求任意两点之间的最短路径

void floyd()
{
    for(int k=0;ke[i][k]+e[k][j])
                    e[i][j]=e[i][k]+e[k][j];
            }
        }
    }

2.2 Dijkstra算法

和Prim算法类似

  1. 初始化:以给定的s作为源点,标记为visit(加入集合),剩下的点与该点的距离作为到该该点的初始化距离。
  2. 加入新点:剩下点中,到s最近的点index加入到集合中。
  3. 更新距离:剩下点到s的距离d[j]=min(d[j],graph[j][index]+d[index])。
  4. 重复2,3步骤n-1次,即所有节点都加入到集合中。
void dijkstra(int cur)
{
  //1.初始化剩余点到s的距离
  visit[cur] = true;
  for (int i = 0; i < N; i++)
    dist[i] = graph[cur][i]; 
  dist[cur] = 0;

  //4.重复n-1次
  for (int i = 1; i < N; i++)
  {
    //2.选点
    int minTemp = INF, index = -1;
    for (int j = 0; j < N; j++)
    {
      if (!visit[j] && dist[j] <= minTemp)
      {
        minTemp = dist[j];
        index = j;
      }
    }
    visit[index] = true;
    //3.更新距离
    for (int j = 0; j < N; j++)
      if (!visit[j] && graph[j][index] != INF)
        dist[j] = min(dist[j], graph[j][index] + dist[index]);
  }
}
#include
#include
#include
#define INF 10000
using namespace std;

const int N = 6; 
vector visit(N, false);  //每个顶点得到最短路径的标记
vector dist(N, 0); //剩下顶点到s的距离
int graph[N][N] = {
{ INF,7,4,INF,INF,INF },
{ 7,INF,6,2,INF,4 },
{ 4,6,INF,INF,9,8 },
{ INF,2,INF,INF,INF,7 },
{ INF,INF,9,INF,INF,1 },
{ INF,4,8,7,1,INF }
};

int main()
{
  dijkstra(0); //以顶点0作为源点s,更新dist数组
  for (int i = 0; i

你可能感兴趣的:(图论)