グラフ理論の基本と応用
基本
図の表現。
隣接行列と隣接リストは、図の表現であります
- 隣接行列:密集するため、図は、適切な(辺の数は、完全グラフに近いです)
- 隣接リスト:スパースグラフの(完全グラフのエッジの数よりはるかに少ないです)
互いに素セット
最小スパニングツリー
コードのステップ
- エッジの定義された一連
- 互いに素セットの一部
- クラスカルのアルゴリズムの部分: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;
}
最短パス - ダイクストラ法
連図解く単一始点最短経路は、最短経路は、出発点の他の点に与えます。
第2スケール:複数の最短パスがある、例えば測定する第2のスケールとして:右側(最小コスト)、最短距離の右点(最大需要)数
コードのステップ
1.初期化
- 最短距離
D [U]:D [S ] = 0 その他D [U] = INF - 右側
C [U]:C [S ] = 0 その他のC [U] = INF - 点右
W [U]:W [S ] =量[S] 他のW [U] = 0 - 最短距離の数
NUM [U]:NUM [S ] = 1 さもなければNUM [U] = 0
(N回のステップのサイクルをすべてのノードは、n訪問まで)
2 D [U] U最小ノードことを見つけるために、セットにアクセスできない
3 Uアクセスノード、すなわちノードは、Uが置かれていますセットS訪問
dのすべての中間ノードを更新するように[V] U:4.最適化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;
}