图论 图的存储结构 点:只关注顶点的编号,可以不存储;如果存储,可以使用线性表存储图的顶点集合(v1,v2,….vn)
边:采用邻接矩阵,邻接表,边表表示
邻接矩阵
顶点表: 用一个一维数组 存储图中顶点的信息,
边表:用一个二维数组 存储图中边的信息,存储顶点之间邻接关系的二维数组称为邻接矩阵
1 2 3 4 5 6 7 8 #define MaxVertexNum 100 typedef char VertexType typedef int EdgeType typedef struct { VertexType Vex[MaxVertexNum]; EdgeType Edge[MaxVertexNum][MaxVertexNum]; int vexnum,arcnum; } MGraph;
邻接表 用线性表存储每个顶点发出的边。定长数组A[n][d],可变长数组vector
1 2 3 4 5 6 7 8 vector<int > Grap [numP]; Grap[i].push_back (j); const int maxn =1e4 +10 ;vector<pair<int ,int >> E[maxn]; Grap[i][j];
邻接链表 对于每个顶点建立一个单链表,第i个单链表中的结点包含顶点$v_i$的所有邻接顶点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 struct Node { int index; int cost; struct Node * link ; }; struct HeadNode { int index; struct Node *adjacent ; }; typedef struct { HeadNode* Grap= new HeadNode[vexnum]; int vexnum; } MGraph;
邻接链表表示无向图
邻接链表 V.S. 邻接矩阵
图的遍历 最小生成树 最短路问题 对于无权图而言,可以利用广度优先搜索查找单源最短路径
对于有权图而言,可以利用Dijkstra算法计算单源最短路径,利用Floyd算法计算顶点之间的最短路
Dijkstra算法 保存的数据:
算法步骤:(默认源点为v0)
初始化,集合S初始化为{0},dist[]的初始值为 dist[i] = arcs[0][i], i=1,2,..n-1
从顶点集合 V-S中选择出 $v_j$,满足$dist[j] =Min (dist[i] | v_i \in V-S )$, $ v_j$就是当前求得的,一条从v0出发的最短路径的终点
修改从v0出发到集合 V-S上的任一顶点 vk可达的最短路径长度:如果dist[j]+ arcs[j][k] <dist[k] ,则更新dist[k] = sidt[j]+arcs[j][k];
重复步骤 2-3,操作共n-1次,直到所有顶点都包含在S中
图结构采用邻接链表的方式存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #include <iostream> struct Node { int index; int cost; struct Node * link ; }; struct HeadNode { int index; struct Node *adjacent ; }; HeadNode* CreatGrap (int Pnum,int Enum) { HeadNode* Head = new HeadNode[Pnum]; for (int i=0 ;i<Enum;i++){ int strP =0 ; int endP= 0 ; int cost; std::cin>>strP>>endP>>cost; Node* temp = new Node (); temp->index=endP; temp->cost=cost; temp->link = NULL ; if (Head[strP].adjacent==NULL ){ Head[strP].adjacent = temp; } else { Node* ptr=Head[strP].adjacent; for (;ptr->link;ptr=ptr->link){} ptr->link = temp; } } return Head; } int * Dijkstra (int v,int Pnum,HeadNode* Head) { int *pre = new int [Pnum]; int *dist = new int [Pnum]; int *s = new int [Pnum]; for (int i = 1 ; i < Pnum; i++) { pre[i] = -1 ; dist[i] = 0x0fff ; s[i] = 0 ; } dist[v] = 0 ; for (int j = 1 ; j < Pnum; j++) { int mindist = 0x0fff ; int u = 0 ; for (int i = 1 ; i < Pnum; i++) { if (dist[i] < mindist && s[i] == 0 ) { mindist = dist[i]; u = i; } } s[u] = 1 ; for (Node *p = Head[u].adjacent; p; p = p->link) { int k = p->index; if (dist[u] + p->cost < dist[k]) { dist[k] = dist[u] + p->cost; pre[k] = u; } } } return pre; } int main () { int Pnum=0 ; int Enum=0 ; std::cout<<"依次输入顶点的个数,边的个数,以及边的起点,终点,权重" <<std::endl; std::cin>> Pnum; std::cin>> Enum; HeadNode* headlist = CreatGrap (Pnum,Enum); int strP = 0 ; int endP =0 ; std::cout<<"输入你要计算最短路径的起点和终点" <<std::endl; std::cin>>strP>>endP; int * pre = Dijkstra (strP,Pnum,headlist); std::cout<<endP; int end=pre[endP]; while (end!=strP){ std::cout<<" " <<end; end = pre[end]; } std::cout<<" " <<strP; }
两点之间的所有最短路 队列优化的Dijkstra算法 pat1003
解法1(有一点问题) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void AdvancedDijkstra (int s) { fill (dis,dis+maxN,0x3fffffff ); dis[s]=0 ; priority_queue<pair<int ,int >> q; q.push (make_pair (0 ,s)); while (!q.empty ()){ int u = q.top ().second; q.pop (); if ( vis[u]==1 ) continue ; vis[u]=1 ; for (int i=0 ;i<E[u].size ();++i){ int v = E[u][i].first,w =E[u][i].second; if (dis[v]>dis[u]+w){ dis[v]=dis[u]+w; num[v]=num[u]; pre[v].clear (); pre[v].push_back (u); MaxCost[v]=MaxCost[u]+cost[v]; if (vis[v]==0 ) q.push (make_pair (-dis[v],v)); } else if (dis[v]==dis[u]+w){ pre[v].push_back (u); num[v]+=num[u]; if (MaxCost[v]<MaxCost[u]+cost[v]){ MaxCost[v]=MaxCost[u]+cost[v]; } if (vis[v]==0 ) q.push (make_pair (-dis[v],v)); } } } }
解法2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <bits/stdc++.h> #include <iostream> using namespace std;const int MaxN = 510 ;const int INF = 0x3fffffff ;int edge[MaxN][MaxN],dist[MaxN],num[MaxN],MaxCost[MaxN],Cost[MaxN];bool vis[MaxN];void Dijkstra (int s,int numP) { num[s]=1 ; MaxCost[s]=Cost[s]; dist[s]=0 ; for (int i=0 ;i<numP;i++){ int MinDis = INF; int u=-1 ; for (int j=0 ;j<numP;j++) { if (MinDis > dist[j] && !vis[j]) { MinDis = dist[j]; u = j; } } if (u==-1 ) { return ; } vis[u]=true ; for (int j=0 ;j<numP;j++){ if (edge[u][j]+dist[u]<dist[j]){ dist[j]=edge[u][j]+dist[u]; num[j]=num[u]; MaxCost[j]=MaxCost[u]+Cost[j]; } else if (edge[u][j]+dist[u] == dist[j]){ num[j]+=num[u]; if (MaxCost[j]<MaxCost[u]+Cost[j]){ MaxCost[j]=MaxCost[u]+Cost[j]; } } } } }