创建: 2018/06/01

图的概念

有向边

有向图

无向边

无向图

点的次数: 点连接的边的数量

闭路: 起点和重点一样

连接图: 任意两点之间都可到达

无闭路有向图: 没有闭路的有向图

森林: 互素的树的集合

生成树: 含有图里所有点的树

生成树林: 所有生成树的并集

   
   
图论算法的应用  
 

● 电路的元件关系

● 交通网

● 电脑网络(本地网络, 互联网, web等)

● 数据库(实体关系图(ER图))

   
图的数据结构  
 邻接矩阵

适用于数据多的

//------------------------------------------------
// 邻接矩阵
//------------------------------------------------
struct Graph {
int v;
int e;
int **adj;
}; // 创建图
struct Graph *adjMatrixOfGraph() {
int i, u, v;
struct Graph *G = (struct Graph *)malloc(sizeof(struct Graph));
if (G == NULL) {
printf("memory error\n");
return NULL;
}
printf("Number of Verticees: ");
scanf("%d", &G->v);
printf("Number of Edges: ");
scanf("%d", &G->e);
G->adj = (int **)malloc(sizeof(int *) * G->v);
if (G->adj == NULL) {
printf("Memory Error\n");
return NULL;
}
for (i = ; i < G->v; i++) {
G->adj[i] = (int *)malloc(sizeof(int) * G->v);
if (G->adj[i] == NULL) {
printf("Memory Error\n");
return NULL;
}
}
printf("v: %d, e: %d\n", G->v, G->e);
for (u=; u<G->v; u++) { // 初始化点
for (v=; v<G->v; v++) {
if (u==v) {
G->adj[u][v] = ;
} else {
G->adj[u][v] = ; // 以0初始化矩阵
}
}
} for (i=; i<G->e; i++) { // 初始化边
printf("Reading Edge: ");
scanf("%d %d", &u, &v);
G->adj[u][v] = G->adj[v][u] = ;
}
return G;
}
 邻接链表 

适用于数据小的

//------------------------------------------------
// 邻接链表
//------------------------------------------------
struct S9ListNode {
int vertexNumber;
struct S9ListNode *next;
}; struct ListGraph {
int v;
int e;
struct S9ListNode *adj;
}; struct ListGraph *adjListOfGraph() { // 无向图
int i, x, y;
struct S9ListNode *temp;
struct ListGraph *G = (struct ListGraph *)malloc(sizeof(struct ListGraph));
if (G == NULL) {
printf("Memory Error\n");
return NULL;
}
printf("Number of Vertices: ");
scanf("%d", &G->v);
printf("Number of Edges: ");
scanf("%d", &G->e);
G->adj = (struct S9ListNode *)malloc(sizeof(struct S9ListNode)*G->v);
if (G->adj == NULL) {
printf("Memory Error\n");
return NULL;
}
for (i=; i<G->v; i++) { // 先初始化所有链表
G->adj[i] = *(struct S9ListNode *)malloc(sizeof(struct S9ListNode));
G->adj[i].vertexNumber = i;
G->adj[i].next = &G->adj[i];
} for (i=; i<G->e; i++) {
printf("Reading Edge: ");
scanf("%d %d", &x, &y);
struct S9ListNode *node;
temp = (struct S9ListNode *)malloc(sizeof(struct S9ListNode));
// 把y添加到x的链表上
temp->vertexNumber = y;
temp->next = &G->adj[x];
node = &G->adj[x];
while (node != NULL && node->next != &G->adj[x]) {
node = node->next;
}
node->next = temp;
// 把x添加到y的链表山
temp = (struct S9ListNode *)malloc(sizeof(struct S9ListNode));
temp->vertexNumber = x;
temp->next = &G->adj[y];
node = &G->adj[y];
while (node != NULL && node->next != &G->adj[y]) {
node = node->next;
}
node->next = temp;
}
return G;
}
   
图的遍历

DFS

深度优先搜索

Depth First Search

//------------------------------------------------
// 深度优先搜索 DFS
//------------------------------------------------
int visited[]; // 实际只需要点的数量的长度
// 状态: 1: 已访问 0: 未访问
// 邻接矩阵的DFS
void depthFirstSearch(struct Graph *g, int u) {
int v;
visited[u] = ;
printf("%d visited\n", u); // 访问中的处理
for (v = ; v <g->v; v++) {
// 对点u连接的未访问的节点进行访问
if (visited[v] == && g->adj[u][v] != ) { // 节点并未访问且u和v连接
depthFirstSearch(g, v); // 从v出发
}
}
} void depthFirstSearchTraversal(struct Graph *g) {
int i;
for (i = ; i < g->v; i++) { // 初始化访问表
visited[i] = ;
}
// 有不通的子连接图时需要
for (i = ; i < g->v; i++) {
if (visited[i] == ) {
depthFirstSearch(g, i); // 一次呼出直接遍历完i可到的所有点
}
}
} // 邻接链表的DFS
void depthFirstSearch_List(struct ListGraph *g, int u) {
struct S9ListNode *temp = g->adj[u].next;
visited[u] = ;
printf("%d visited\n", u); // 访问中的处理
while (temp != &g->adj[u]) {
if (visited[temp->vertexNumber] == ) {
depthFirstSearch_List(g, temp->vertexNumber);
}
temp = temp->next;
} } void depthFirstSearchTraversal_List(struct ListGraph *g) {
int i;
for (i = ; i < g->v; i++) { // 初始化访问表
visited[i] = ;
}
// 有不通的子连接图时需要
for (i = ; i < g->v; i++) {
if (visited[i] == ) {
depthFirstSearch_List(g, i); // 一次呼出直接遍历完i可到的所有点
}
}
}

BFS

宽度优先搜索

Breadth First Search

//------------------------------------------------
// 宽度优先搜索 BFS
//------------------------------------------------
struct S9QueueNode {
int data;
struct S9QueueNode *next;
};
struct S9Queue {
struct S9QueueNode *front;
}; struct S9Queue *S9CreateQueue() {
struct S9Queue *q = (struct S9Queue *)malloc(sizeof(struct S9Queue));
if (q == NULL) {
return NULL;
}
q->front = NULL;
return q;
} int S9DeQueue(struct S9Queue *queue) {
if (queue==NULL) {
return -;
}
if (queue->front == NULL) {
return -;
}
struct S9QueueNode *temp = queue->front;
if (queue->front == NULL) {
return -;
}
int data = temp->data;
queue->front = queue->front->next;
free(temp);
return data;
}
void S9EnQueue(struct S9Queue *queue, int data) {
if (queue == NULL) {
queue = (struct S9Queue *)malloc(sizeof(struct S9Queue));
}
struct S9QueueNode *newNode = (struct S9QueueNode *)malloc(sizeof(struct S9QueueNode));
struct S9QueueNode *temp = queue->front;
newNode->next = NULL;
newNode->data = data;
if (temp == NULL) {
queue->front = newNode;
} else {
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
} void S9FreeQueue(struct S9Queue *q) {
if (q == NULL) {
return;
}
if (q->front != NULL) {
struct S9QueueNode *temp = q->front, *temp2;
while (temp != NULL) {
temp2 = temp;
temp = temp->next;
free(temp2);
}
}
free(q);
} int S9IsEmptyQueue(struct S9Queue *queue) { // true: 1, false: 0
if (queue == NULL) {
return ;
}
int result = queue->front == NULL ? : ;
return result;
}
void S9ShowQueue(struct S9Queue *q) {
if (q == NULL) {
printf("queue is null\n");
return;
}
if (q->front == NULL) {
printf("queue has no data\n");
return;
}
struct S9QueueNode *temp = q->front;
int count = ;
while (temp) {
printf("[%d]: %d ", count, temp->data);
temp = temp->next;
count++;
}
puts("");
} int visited_bfs[];
void breadthFirstSearch(struct Graph *g, int u) { // 矩阵
int count = , i;
struct S9Queue *queue = S9CreateQueue();
S9EnQueue(queue, u);
while (!S9IsEmptyQueue(queue)) {
int u = S9DeQueue(queue);
printf("顶点[%d]: %d\n", count, u);
count++;
visited_bfs[u] = ;
for (i=; i<g->v; i++) {
if (g->adj[u][i] == && visited_bfs[i] == ) {
S9EnQueue(queue, i);
}
}
}
S9FreeQueue(queue);
}
void breadthFirstSearchTravsal(struct Graph *g) {
for (int i=; i<; i++) {
visited_bfs[i] = ;
}
for (int i = ; i<g->v; i++) {
if (visited_bfs[i] == ) {
breadthFirstSearch(g, i);
}
}
}
   
最短路径算法  
 种类

● 不带加权的图

● 带加权的图

● 有负加权的图

 应用 

● 两地间最近的路

●  从A到B发送数据最便宜的方法

 不加权的图最短路径
//------------------------------------------------
// 不带加权的图
//------------------------------------------------
int distant[];
int path[];
void unweightedShortestPath(struct Graph *g, int s) { // 邻接矩阵版
struct S9Queue *queue = S9CreateQueue();
int v, w;
S9EnQueue(queue, s);
for (int i = ; i<g->v; i++) {
distant[i] = -;
path[i] = -; // 起点为-1
}
distant[s] = ;
while(!S9IsEmptyQueue(queue)) {
v = S9DeQueue(queue);
for (w = ; w<g->v; w++) {
if (g->adj[v][w] != && distant[w] == -) {
S9EnQueue(queue, w);
distant[w] = distant[v] + ;
path[w] = v;
}
}
}
S9FreeQueue(queue);
}

迪杰斯特拉算法

加权图最短路径算法

//------------------------------------------------
// 不带负加权的图 迪杰斯特拉算法
//------------------------------------------------
void dijkstra(struct Graph *g, int s) {
struct S9Queue *queue = S9CreateQueue(); // 优先队列
int v, w;
S9EnQueue(queue, s);
for (int i = ; i<g->v; i++) {
distant[i] = -; // -1 表示还没处理
}
distant[s] = ; // 自己到自己的距离为0
while (!S9IsEmptyQueue(queue)) {
// v = S9DeQueue(queue); // TODO-PRO: fix here [这里要改成以距离为排序的DeleteMin]
v = S9DeleteMin(queue);
for (w = ; w<g->v; w++) {
if (g->adj[v][w] != ) { // v -> w 直接相同
int newDistant = distant[v] + g->adj[v][w]; // 新距离
printf("distant[v]: %d\n", distant[v]);
if (distant[w] == -) {
distant[w] = newDistant;
S9EnQueue(queue, w);
path[w] = v;
} else if (newDistant < distant[w]) {
distant[w] = newDistant;
path[w] = v;
// 更新w
S9EnQueue(queue, w);
}
}
}
}
}
 贝尔曼-福特算法  可以有负加权边
   

【WIP_S9】图论算法的更多相关文章

  1. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  2. 图论算法-网络最大流【EK;Dinic】

    图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...

  3. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  4. tarjan图论算法

    tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...

  5. [算法模版]Tarjan爷爷的几种图论算法

    [算法模版]Tarjan爷爷的几种图论算法 前言 Tarjan爷爷发明了很多图论算法,这些图论算法有很多相似之处(其中一个就是我都不会).这里会对这三种算法进行简单介绍. 定义 强连通(strongl ...

  6. NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...

  7. NOIp 图论算法专题总结 (2)

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 树链剖分 https://oi-wiki.org/graph/heavy-lig ...

  8. NOIp 图论算法专题总结 (3):网络流 & 二分图 简明讲义

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 网络流 概念 1 容量网络(capacity network)是一个有向图,图的 ...

  9. 图论算法(一)存图与STL第六弹——vector容器

    图论算法(一)存图 我发现我的博客阅读量贼低,问小伙伴们,ta们都说这些博客太长了QAQ! 今天来个短亿点的(也短不了多少……) 进入正题,图论究竟是什么? 图论就是给你一张图,让你在这张图上进行各种 ...

随机推荐

  1. redis文档翻译_LRU缓存

    Using Redis as an LRU cache使用Redis作为LRU缓存 出处:http://blog.csdn.net/column/details/redisbanli.html Whe ...

  2. EasyDarwin流媒体服务器高性能优化方向

    我们在EasyDarwin开源流媒体服务器上做了很多的优化,包括前面说到的<EasyDarwin开源流媒体服务器将select改为epoll的方法>.<EasyDarwin开源流媒体 ...

  3. service oriented architecture 构造分布式计算的应用程序的方法 面向服务的架构 分解技术

    zh.wikipedia.org/wiki/面向服务的架构 [程序功能做为服务] 面向服务的体系结构(英语:service-oriented architecture)是构造分布式計算的应用程序的方法 ...

  4. 使用MSSQL同步&发布数据库快照遇到错误:对路径“xxxxx”访问被拒绝的解决方法

    使用MSSQL同步 数据库同步做后后测试:先在同步那台服务器(服务器A)数据库里修改里面数据库,然后再去被同步那台服务器(服务器B)看下数据有没被同步过去 发布数据库快照遇到错误:对路径“xxxxx” ...

  5. Codeforces 724C Ray Tracing 扩展欧几里得

    吐槽:在比赛的时候,压根就没想到这题还可以对称: 题解:http://blog.csdn.net/danliwoo/article/details/52761839 比较详细: #include< ...

  6. 【Advanced Windows Phone Programming】在windows phone 8中解码mp3 和编码pcm

    转眼间不做wp开发,投身于php事业已然一年了,转身看到8.1的发布,俨然一片欣欣向荣的景象,但是开发社区却没比一年前有过多大的提高,这并不是一个好现象,遂在git上开源了之前音频处理库,希望能对社区 ...

  7. 分布式版本控制系统—git命令

    一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...

  8. cookie(点心的意思)服务器给客户端的点心

    他是用户访问web服务器时,服务器在用户硬盘上存放的信息,好像是服务器给客户端的“点心”.比如:是否记录用户名密码.其中,A服务器不允许访问B服务器存在客户端的cookie 一个cookie包含一对k ...

  9. scanf()函数

    Scanf函数攻略: (A)                格式化说明符 格式字符           说明 %d                 读入十进制整数 %u                 ...

  10. 001 - 配置Pycharm的字体大小

    本文记录的是Pycharm2017年1月版本 1 配置代码区的字体大小 位置在 File -> setting -> Editor -> Color&Fonts -> ...