Теория графов фундаментальная и прикладная

основы

Представление фиг.

представление чертежей являются матрица смежности и присоединенные списки

  1. Матрица смежности: фиг подходит для плотного (число ребер близко к полному графику)
  2. Списки смежности: для разреженных графов (гораздо меньше, чем число ребер в полном графе)

Disjoint-набор

Минимального остовного дерева

Код Шаг

  1. Определено множество ребер
  2. Disjoint-часть набора
  3. Алгоритм Крускала части: 1) Инициализация 2 непересекающихся-набор) в порядке возрастания правой боковой кромки рода 3) перемещения кромки

реализация кода

//图
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXV = 1010;
const int MAXE = 1010;

//边集定义部分
struct edge {
	int u, v;
	int cost;
}E[MAXE];
bool cmp(edge a, edge b) {
		return a.cost < b.cost;
}

//并查集部分
int Tree[MAXV];
int findRoot(int x)
{
	if (Tree[x] == -1) return x;
	else
	{
		int temp = findRoot(Tree[x]);
		Tree[x] = temp;
		return temp;
	}
}

//kruskal部分
int kruskal(int n, int m)
{
	//n:顶点数,m:边数
	int ans = 0; int Num_Edge = 0;
	for (int i = 1; i <= n; i++)
		Tree[i] = -1;
	sort(E + 1, E + m + 1, cmp);
	for (int i = 1; i <= m; i++)
	{
		int a = findRoot(E[i].u);
		int b = findRoot(E[i].v);
		if (a != b)
		{
			Tree[a] = b;
			ans = ans + E[i].cost;
			Num_Edge++;
		}
		if (Num_Edge == n - 1) break;
	}
	if (Num_Edge == n - 1) return ans;
	else return -1;
}


int main()
{
	int n;
	while (scanf("%d", &n) != EOF && n != 0)
	{
		int m = n * (n - 1) / 2;
		for (int i = 1; i <= m; i++)
			scanf("%d %d %d", &E[i].u, &E[i].v, &E[i].cost);
		cout << kruskal(n, m) << endl;

	}

	system("pause");
	return 0;


}

Кратчайший путь - алгоритм Дейкстры

Решение сообщающегося фиг из одного источника кратчайшего пути , самый короткий путь , чтобы дать отправную точку s к другим точкам.
Второй масштаб: когда есть несколько кратчайших пути, как вторая шкала для измерения, например: правая сторона (минимальная стоимость), правая точка (максимальный спрос) количество кратчайшего расстояния

Код Шаг

1. Инициализация

  1. Кратчайшее расстояние
    d [U]: d [S ] = 0 другой д [и] = INF
  2. Правая сторона
    с [и]: C [S ] = 0 друга с [и] = INF
  3. Точка вправо
    ш [и]: ш [с ] = вес [с] другой ш [и] = 0
  4. Количество кратчайшего расстояния
    NUM [и]: Num [S ] = 1 еще Num [и] = 0

(N раз цикл шагов , пока все узлы не посещали п)
2 не доступен в наборе, чтобы найти , что D [и] у минимального узла
3. Узел доступа и, т.е. узел был положим и посетили множество S
4. оптимизация д [V]: и, чтобы обновить все промежуточные узлы d [v]

реализация кода

//开始玩转Dijkstra
//Dijkstra模板
//模板思路:1)在未访问的点的集合中寻找使d[u]最小的u	2)在未访问的结点中,更新所有以u为中间结点的d[v]

#include <iostream>

using namespace std;

const int MAXV = 1100;
const int INF = 1e9;

int G[MAXV][MAXV];  //存放图,以邻接矩阵的形式
int d[MAXV];		//当前最短路径:起点到达各个终点的最短路径长度  d[u]:源结点s到结点u的最短路径
bool visit[MAXV] = {false};	//用来判断当前节点是否已经被访问

void dijkstra(int n, int s)
{
	//n为顶点数,s为起始节点

	//数组d[MAXV]的初始化
	fill(d + 1, d + n + 1, INF);
	d[s] = 0;

	for (int i = 1; i <= n; i++)
	{
		//寻找最小的d[u]的标号u
		int temp = INF; int u;
		for (int j = 1; j <= n; j++)
		{
			if (visit[j] == false && d[j] < temp)
			{
				temp = d[j];
				u = j;
			}
		}
		visit[u] = true;
		for (int v = 1; v <= n; v++)
		{
			if (visit[v] == false && G[u][v] != INF && G[u][v] + d[u] < d[v])
				d[v] = G[u][v] + d[u];
		}
	}


}

int main()
{
	int n, m,s;
	int u, v, cost;
	scanf("%d %d %d", &n, &m, &s);
	fill(G[0], G[0] + MAXV * MAXV, INF);
	for (int i = 1; i <= m; i++)
	{
		scanf("%d %d %d", &u, &v, &cost);
		G[u][v] = cost;
	}
	dijkstra(n, s);
	for (int i = 1; i <= n; i++)
		cout << d[i] << " ";
	
	system("pause");
	return 0;
}
Освобожденные девять оригинальных статей · вона похвала 4 · Просмотров 1018

рекомендация

отblog.csdn.net/L18273121172/article/details/90513866