数据结构学习第二十一天

23:34:47 2019-09-06

学校未开课 继续接着暑假学习

PTA第21题 Prim最小树生成

  1 #define _CRT_SECURE_NO_WARNINGS  
  2 #include<stdio.h>
  3 #include<malloc.h>
  4 #define INIFITY 65635
  5 
  6 typedef int Vertex;
  7 typedef struct ENode* Edge;
  8 struct ENode
  9 {
 10     Vertex    V1, V2;
 11     int Weight;
 12 };
 13 
 14 typedef struct Graph* MGraph;
 15 struct Graph
 16 {
 17     int Nv;
 18     int Ne;
 19     int G[1001][1001];
 20 };
 21 
 22 MGraph CreateGraph(int VertexNum)
 23 {
 24     MGraph Graph = (MGraph)malloc(sizeof(struct Graph));
 25     Graph->Nv = VertexNum;
 26     Graph->Ne = 0;
 27     for (int i = 0; i < Graph->Nv; i++)
 28         for (int j = 0; j < Graph->Nv; j++)
 29             Graph->G[i][j] = INIFITY;
 30     return Graph;
 31 }
 32 
 33 void Insert(MGraph Graph, Edge E)
 34 {
 35     Graph->G[E->V1][E->V2] = E->Weight;
 36     Graph->G[E->V2][E->V1] = E->Weight;
 37 }
 38 
 39 MGraph BuildGraph()
 40 {
 41     int Nv;
 42     Edge E;
 43     scanf("%d", &Nv);
 44     MGraph Graph = CreateGraph(Nv);
 45     scanf("%d
", &(Graph->Ne));
 46     for (int i = 0; i < Graph->Ne; i++)
 47     {
 48         E = (Edge)malloc(sizeof(struct ENode));
 49         scanf("%d %d %d
", &(E->V1), &(E->V2), &(E->Weight));
 50         Insert(Graph, E);
 51     }
 52     return Graph;
 53 }
 54 
 55 int IsEdge(MGraph Graph, Vertex V, Vertex W)
 56 {
 57     return (Graph->G[V][W] < INIFITY) ? 1 : 0;
 58 }
 59 //利用Prim算法 解决最小生成树的问题
 60 
 61 int Dist[1001];  //表示某点到树的距离
 62 int Parent[1001];
 63 int TotalWeight;    //表示总的成本
 64 int VCount;  //表示收录的点数
 65 int FindMinDist(MGraph Graph)
 66 {
 67     int MinDist = INIFITY;
 68     int MinV;
 69     for (int i = 0; i < Graph->Nv; i++)
 70     {
 71         if (Dist[i]!=-1&& Dist[i] < MinDist)
 72         {
 73             MinDist = Dist[i];
 74             MinV = i;
 75         }
 76     }
 77     if (MinDist < INIFITY)
 78         return MinV;
 79     else
 80         return 0;
 81 }
 82 int Prim(MGraph Graph, Vertex S)
 83 {
 84     for (int i = 0; i < Graph->Nv; i++)
 85     {
 86         Dist[i] = Graph->G[S][i];
 87         if (Dist[i] < INIFITY)
 88             Parent[i] = S;
 89         else
 90             Parent[i] = -1;
 91     }
 92     Dist[S] = -1;
 93     Parent[S] = -1;
 94     VCount++;
 95     while (1)
 96     {
 97         int V = FindMinDist(Graph);
 98         if (!V)
 99             break;
100         TotalWeight += Dist[V];
101         Dist[V] = -1;
102         VCount++;
103         for (int i = 0; i < Graph->Nv; i++)
104         {
105             if (Dist[i]!=-1&& IsEdge(Graph, V, i))
106             {
107                 if (Graph->G[V][i] < Dist[i])
108                 {
109                     Dist[i] = Graph->G[V][i];
110                     Parent[i] = V;
111                 }
112             }
113         }
114     }
115     if (VCount <Graph->Nv)
116         return -1;
117     else
118         return TotalWeight;
119 }
120 int main()
121 {
122     MGraph Graph = BuildGraph();
123     printf("%d", Prim(Graph, 0));
124     return 0;
125 }
View Code

拓扑排序

拓扑序:如果图中从V到W有一条有向路径,则V一定排在W之前.满足此条件的顶点序列称为一个拓扑序

获得一个拓扑序的过程就是拓扑排序

AOV(Acitivity On Vertex)网络 如果有合理的拓扑序,则必定是有向无环图(Directed Acyclic Graph,DAG)

关键路径问题(拓扑排序应用)

AOE(Acitivity On Edge)网络  (os:PTA上有道题看了我好长时间都不会 。。果然我不看教程就啥也不会)

  一般用于安排项目的工序

关键路径问题 中

最短时间

$Earliest[0]=0; \ Earliest[j]=mathop{max}limits_{<i,j>in E} {Earliest[i]+C_<i,j>}$

在保证最短时间下计算机动时间

机动时间: $D_<i,j>=Latest[j]-Earliest[i]-C_<i,j>$

$Latest[Last]=Earliest[Last]$     //Last表示最后一个节点

$Latest[i]=mathop{min}limits_{<i,j>in E} {Earlist[j]-C_<i,j>}$

关键路径 由绝对不允许延误的活动组成的路径(没有机动时间)

拓扑排序

  1 #define _CRT_SECURE_NO_WARNINGS  
  2 #include<stdio.h>
  3 #include<malloc.h>
  4 //表示图的两种方法
  5 //邻接矩阵 G[N][N] N个顶点从0到N-1编号
  6 //邻接表 表示
  7 /*Graph Create();  //建立并返回空图
  8 Graph InsertVertex(Graph G, Vertex v); //将v插入G
  9 Graph InsertEdge(Graph G, Edge e); //将e插入G
 10 void DFS(Graph G, Vertex v); //从顶点v出发深度优先遍历图G
 11 void BFS(Graph G, Vertex v); //从顶点v出发宽度优先遍历图G
 12 void ShortestPath(Graph G, Vertex v, int Dist[]); //计算图G中顶点v到任意其它顶点的最短距离
 13 void MST(Graph G); //计算图G的最小生成树*/
 14 //图的邻接表表示法
 15 #define MaxVerterNum 100    //最大顶点数
 16 #define INFINITY 65535        //
 17 typedef int Vertex;            //顶点下标表示顶点
 18 typedef int WeightType;        //边的权值
 19 typedef char DataType;        //顶点存储的数据类型
 20 
 21 //边的定义
 22 typedef struct ENode* PtrToENode;
 23 typedef PtrToENode Edge;
 24 struct ENode
 25 {
 26     Vertex V1, V2; //有向边<V1,V2>
 27     WeightType Weight;  //权重
 28 };
 29 
 30 //邻接点的定义
 31 typedef struct AdjVNode* PtrToAdjVNode;
 32 struct AdjVNode
 33 {
 34     Vertex AdjV;  //邻接点下标
 35     WeightType Weight; //边权重
 36     PtrToAdjVNode Next; //指向下一个邻接点的指针
 37 };
 38 
 39 //顶点表头节点的定义
 40 typedef struct Vnode
 41 {
 42     PtrToAdjVNode FirstEdge;  //边表头指针
 43     DataType Data;            //存顶点的数据
 44     int Indegree;            //入度
 45 }AdjList[MaxVerterNum];        //AdjList是邻接表类型
 46 
 47 //图节点的定义
 48 typedef struct GNode* PtrToGNode;
 49 typedef PtrToGNode LGraph;
 50 struct GNode
 51 {
 52     int Nv;  //顶点数
 53     int Ne;  //边数
 54     AdjList G;  //邻接表
 55 };
 56 
 57 LGraph CreateGraph(int VertexNum)
 58 {//初始化一个有VertexNum个顶点但没有边的图
 59     Vertex V;
 60     LGraph Graph;
 61 
 62     Graph = (LGraph)malloc(sizeof(struct GNode)); //建立图
 63     Graph->Nv = VertexNum;
 64     Graph->Ne = 0;
 65     //初始化邻接表头指针
 66     for (V = 0; V < Graph->Nv; V++)
 67         Graph->G[V].FirstEdge = NULL;
 68     return Graph;
 69 }
 70 void InsertEdge(LGraph Graph, Edge E)
 71 {
 72     PtrToAdjVNode NewNode;
 73     //插入边<V1,V2>
 74     NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 75     NewNode->AdjV = E->V2;
 76     NewNode->Weight = E->Weight;
 77     NewNode->Next = Graph->G[E->V1].FirstEdge;
 78     Graph->G[E->V1].FirstEdge = NewNode;
 79     Graph->G[E->V2].Indegree++;
 80 
 81     //若是无向图 还要插入边<V2,V1>
 82     /*NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 83     NewNode->AdjV = E->V1;
 84     NewNode->Weight = E->Weight;
 85     NewNode->Next = Graph->G[E->V2].FirstEdge;
 86     Graph->G[E->V2].FirstEdge = NewNode;*/
 87 }
 88 LGraph BuildGraph()
 89 {
 90     LGraph Graph;
 91     Edge E;
 92     Vertex V;
 93     int Nv, i;
 94 
 95     scanf("%d", &Nv);   /* 读入顶点个数 */
 96     Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */
 97     scanf("%d", &(Graph->Ne));  //读入边数
 98     if (Graph->Ne != 0)
 99     {
100         E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */
101         /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
102         for (i = 0; i < Graph->Ne; i++)
103         {
104             scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
105             InsertEdge(Graph, E);
106         }
107     }
108     /* 如果顶点有数据的话,读入数据 */
109     for (V = 0; V < Graph->Nv; V++)
110         scanf(" %c", &(Graph->G[V].Data));
111     return Graph;
112 }
113 
114 #define Size 100
115 int Queue[Size];
116 int Front = 1;
117 int Rear = 0;
118 int size = 0;
119 int Succ(int Num)
120 {
121     if (Num < Size)
122         return Num;
123     else
124         return 0;
125 }
126 void EnQueue(int Num)
127 {
128     Rear = Succ(Rear + 1);
129     Queue[Rear] = Num;
130     size++;
131 }
132 int DeQueue()
133 {
134     int Num = Queue[Front];
135     Front = Succ(Front + 1);
136     size--;
137     return Num;
138 }
139 int IsEmpty()
140 {
141     return (size == 0) ? 1 : 0;
142 }
143 
144 //利用邻接表实现拓扑排序
145 int TopOrder[100];  //顺序存储排序后的顶点下标
146 int TopSort(LGraph Graph)
147 {        //对Graph进为拓扑排序 ,TopOrder[] 顺序存储排序后的顶点下标
148     int Indegree[100];
149     int cnt = 0;
150     for (int i = 0; i < Graph->Nv; i++)    //初始化Indegree
151         Indegree[i] = 0;
152     for(int i=0;i<Graph->Nv;i++)
153         for (PtrToAdjVNode W = Graph->G[i].FirstEdge; W; W = W->Next)
154         {
155             Indegree[W->AdjV]++;
156         }
157     for (int i = 0; i < Graph->Nv; i++)
158         if (Indegree[i] == 0)
159             EnQueue(i);
160 
161     //进入拓扑排序
162     while (!IsEmpty())
163     {
164         int V = DeQueue();
165         TopOrder[cnt++] = V;
166         for (PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W = W->Next)
167             if (--Indegree[W->AdjV] == 0)
168                 EnQueue(W->AdjV);
169     }
170     if (cnt != Graph->Nv)
171         return 0;
172     else
173         return 1;
174 }
View Code

PTA 第22题 拓扑排序(关键路径)  注意关键路径找完成时间时 取所有中最大值

  1 #define _CRT_SECURE_NO_WARNINGS  
  2 #include<stdio.h>
  3 #include<malloc.h>
  4 //表示图的两种方法
  5 //邻接矩阵 G[N][N] N个顶点从0到N-1编号
  6 //邻接表 表示
  7 /*Graph Create();  //建立并返回空图
  8 Graph InsertVertex(Graph G, Vertex v); //将v插入G
  9 Graph InsertEdge(Graph G, Edge e); //将e插入G
 10 void DFS(Graph G, Vertex v); //从顶点v出发深度优先遍历图G
 11 void BFS(Graph G, Vertex v); //从顶点v出发宽度优先遍历图G
 12 void ShortestPath(Graph G, Vertex v, int Dist[]); //计算图G中顶点v到任意其它顶点的最短距离
 13 void MST(Graph G); //计算图G的最小生成树*/
 14 //图的邻接表表示法
 15 #define MaxVerterNum 100    //最大顶点数
 16 #define INFINITY 65535        //
 17 typedef int Vertex;            //顶点下标表示顶点
 18 typedef int WeightType;        //边的权值
 19 typedef char DataType;        //顶点存储的数据类型
 20 
 21 //边的定义
 22 typedef struct ENode* PtrToENode;
 23 typedef PtrToENode Edge;
 24 struct ENode
 25 {
 26     Vertex V1, V2; //有向边<V1,V2>
 27     WeightType Weight;  //权重
 28 };
 29 
 30 //邻接点的定义
 31 typedef struct AdjVNode* PtrToAdjVNode;
 32 struct AdjVNode
 33 {
 34     Vertex AdjV;  //邻接点下标
 35     WeightType Weight; //边权重
 36     PtrToAdjVNode Next; //指向下一个邻接点的指针
 37 };
 38 
 39 //顶点表头节点的定义
 40 typedef struct Vnode
 41 {
 42     PtrToAdjVNode FirstEdge;  //边表头指针
 43     DataType Data;            //存顶点的数据
 44     int Indegree;            //入度
 45 }AdjList[MaxVerterNum];        //AdjList是邻接表类型
 46 
 47 //图节点的定义
 48 typedef struct GNode* PtrToGNode;
 49 typedef PtrToGNode LGraph;
 50 struct GNode
 51 {
 52     int Nv;  //顶点数
 53     int Ne;  //边数
 54     AdjList G;  //邻接表
 55 };
 56 
 57 LGraph CreateGraph(int VertexNum)
 58 {//初始化一个有VertexNum个顶点但没有边的图
 59     Vertex V;
 60     LGraph Graph;
 61 
 62     Graph = (LGraph)malloc(sizeof(struct GNode)); //建立图
 63     Graph->Nv = VertexNum;
 64     Graph->Ne = 0;
 65     //初始化邻接表头指针
 66     for (V = 0; V < Graph->Nv; V++)
 67         Graph->G[V].FirstEdge = NULL;
 68     return Graph;
 69 }
 70 void InsertEdge(LGraph Graph, Edge E)
 71 {
 72     PtrToAdjVNode NewNode;
 73     //插入边<V1,V2>
 74     NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 75     NewNode->AdjV = E->V2;
 76     NewNode->Weight = E->Weight;
 77     NewNode->Next = Graph->G[E->V1].FirstEdge;
 78     Graph->G[E->V1].FirstEdge = NewNode;
 79     Graph->G[E->V2].Indegree++;
 80 
 81     //若是无向图 还要插入边<V2,V1>
 82     /*NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 83     NewNode->AdjV = E->V1;
 84     NewNode->Weight = E->Weight;
 85     NewNode->Next = Graph->G[E->V2].FirstEdge;
 86     Graph->G[E->V2].FirstEdge = NewNode;*/
 87 }
 88 LGraph BuildGraph()
 89 {
 90     LGraph Graph;
 91     Edge E;
 92     Vertex V;
 93     int Nv, i;
 94 
 95     scanf("%d", &Nv);   /* 读入顶点个数 */
 96     Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */
 97     scanf("%d", &(Graph->Ne));  //读入边数
 98     if (Graph->Ne != 0)
 99     {
100         E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */
101         /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
102         for (i = 0; i < Graph->Ne; i++)
103         {
104             scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
105             InsertEdge(Graph, E);
106         }
107     }
108     return Graph;
109 }
110 
111 #define Size 100
112 int Queue[Size];
113 int Front = 1;
114 int Rear = 0;
115 int size = 0;
116 int Succ(int Num)
117 {
118     if (Num < Size)
119         return Num;
120     else
121         return 0;
122 }
123 void EnQueue(int Num)
124 {
125     Rear = Succ(Rear + 1);
126     Queue[Rear] = Num;
127     size++;
128 }
129 int DeQueue()
130 {
131     int Num = Queue[Front];
132     Front = Succ(Front + 1);
133     size--;
134     return Num;
135 }
136 int IsEmpty()
137 {
138     return (size == 0) ? 1 : 0;
139 }
140 
141 //利用邻接表实现拓扑排序
142 int TopOrder[100];  //顺序存储排序后的顶点下标
143 int Earliest[100];
144 int TopSort(LGraph Graph)
145 {        //对Graph进为拓扑排序 ,TopOrder[] 顺序存储排序后的顶点下标
146     int Indegree[100];
147     int cnt = 0;
148     for (int i = 0; i < Graph->Nv; i++)    //初始化Indegree
149         Indegree[i] = 0;
150     for (int i = 0; i < Graph->Nv; i++)
151         for (PtrToAdjVNode W = Graph->G[i].FirstEdge; W; W = W->Next)
152         {
153             Indegree[W->AdjV]++;
154         }
155     for (int i = 0; i < Graph->Nv; i++)
156         if (Indegree[i] == 0)
157         {
158             EnQueue(i);
159             Earliest[i] = 0;
160         }
161     //进入拓扑排序
162     while (!IsEmpty())
163     {
164         int V = DeQueue();
165         TopOrder[cnt++] = V;
166         for (PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W = W->Next)
167         {
168             if (--Indegree[W->AdjV] == 0)
169             {
170                 if ((Earliest[V] + W->Weight) > Earliest[W->AdjV])
171                     Earliest[W->AdjV] = Earliest[V] + W->Weight;
172                 EnQueue(W->AdjV);
173             }
174         }
175     }
176     if (cnt != Graph->Nv)
177         return 0;
178     else
179     {
180         int Max=-1;
181         int V;
182         for (int i = 0; i < Graph->Nv; i++)
183         {
184             if (Earliest[i]>Max)
185             {
186                 Max = Earliest[i];
187                 V = i;
188             }
189         }
190         return Max;
191     }
192 }
193 
194 int main()
195 {
196     LGraph Graph = BuildGraph();
197     int Sum;
198     if (!(Sum = TopSort(Graph)))
199         printf("Impossible");
200     else   //找到最大的那个
201         printf("%d", Sum);
202 }
View Code
原文地址:https://www.cnblogs.com/57one/p/11478894.html