/* 邻接表存储 - 拓扑排序算法 */
bool TopSort( LGraph Graph, Vertex TopOrder[] )
{ /* 对Graph进行拓扑排序, TopOrder[]顺序存储排序后的顶点下标 */
int Indegree[MaxVertexNum], cnt;
Vertex V;
PtrToAdjVNode W;
Queue Q = CreateQueue( Graph->Nv );
/* 初始化Indegree[] */
for (V=0; VNv; V++)
Indegree[V] = 0;
/* 遍历图,得到Indegree[] */
for (V=0; VNv; V++)
for (W=Graph->G[V].FirstEdge; W; W=W->Next)
Indegree[W->AdjV]++; /* 对有向边AdjV>累计终点的入度 */
/* 将所有入度为0的顶点入列 */
for (V=0; VNv; V++)
if ( Indegree[V]==0 )
AddQ(Q, V);
/* 下面进入拓扑排序 */
cnt = 0;
while( !IsEmpty(Q) ){
V = DeleteQ(Q); /* 弹出一个入度为0的顶点 */
TopOrder[cnt++] = V; /* 将之存为结果序列的下一个元素 */
/* 对V的每个邻接点W->AdjV */
for ( W=Graph->G[V].FirstEdge; W; W=W->Next )
if ( --Indegree[W->AdjV] == 0 )/* 若删除V使得W->AdjV入度为0 */
AddQ(Q, W->AdjV); /* 则该顶点入列 */
} /* while结束*/
if ( cnt != Graph->Nv )
return false; /* 说明图中有回路, 返回不成功标志 */
else
return true;
}
Given the relations of all the activities of a project, you are supposed to find the earliest completion time of the project.
Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1), and M, the number of activities. Then M lines follow, each gives the description of an activity. For the i
-th activity, three non-negative numbers are given: S[i]
, E[i]
, and L[i]
, where S[i]
is the index of the starting check point, E[i]
of the ending check point, and L[i]
the lasting time of the activity. The numbers in a line are separated by a space.
For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output "Impossible".
9 12
0 1 6
0 2 4
0 3 5
1 4 1
2 4 1
3 5 2
5 4 0
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4
18
4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5
Impossible
第i行实际上给出的是一条有向边的信息,包括这条边的起点,终点和权值,要求在对这些事件进行拓扑排序后找到完成这系列事件所需时间,暂未涉及到关键路径问题,不要想复杂
难点:
(一)如何建图
第i行实际上给出的是一条有向边的信息,包括这条边的起点,终点和权值
用邻接矩阵建图应该也可以,不过锻炼能力还是用邻接表建图
(二)如何遍历
拓扑排序
关键一:
Earliest的更新:Earliest[i]表示完成节点i所需的最早时间单位,但因为存在不同的依赖关系,所以在若干前置事件完成后必须从中挑出一个最大的
关键二:
不是vertexNums-1就是结束事件,而是要在Earliest数组中找到最大值
#include
#include
#include
#define MAX_NODE_NUMS 105
#define TRUE 1
#define FALSE 0
#define NONE -1
typedef int bool;
/*实现队列的数据结构*/
typedef struct QueueNode QueueNode;
typedef QueueNode* Queue;
struct QueueNode {
int Head, Rear, Size;
int Data[MAX_NODE_NUMS];
};
void InitQueue(Queue* q) {
(*q)->Head = 0;
(*q)->Rear = -1;
(*q)->Size = 0;
for(int i = 0; i < MAX_NODE_NUMS; i++) {
(*q)->Data[i] = NONE;
}
}
bool IsEmpty(Queue* q) {
if((*q)->Size == 0) {
return TRUE;
}
else {
return FALSE;
}
}
bool IsFull(Queue* q) {
if((*q)->Size == MAX_NODE_NUMS) {
return TRUE;
}
else {
return FALSE;
}
}
void Enqueue(Queue* q, int data) {
if(!IsFull(q)) {
(*q)->Data[((*q)->Rear + 1) % MAX_NODE_NUMS] = data;
(*q)->Rear = ((*q)->Rear + 1) % MAX_NODE_NUMS;
(*q)->Size++;
return;
}
}
int Dequeue(Queue* q) {
if(!IsEmpty(q)) {
int ret = (*q)->Data[(*q)->Head];
(*q)->Head = ((*q)->Head + 1) % MAX_NODE_NUMS;
(*q)->Size--;
return ret;
}
}
/*实现邻接表构造的图的数据结构*/
typedef struct EdgeNode EdgeNode;
typedef EdgeNode* PToEdge;
struct EdgeNode {
int Start, End, Weight;
};
typedef struct AdjVNode AdjVNode;
typedef AdjVNode* PToAdjVNode;
struct AdjVNode {
int Index;
int Weight;
PToAdjVNode Next;
};
typedef struct HeadNode HeadNode;
struct HeadNode {
int Data;
PToAdjVNode FirstEdge;
};
typedef struct ListGraphNode ListGraphNode;
typedef ListGraphNode* ListGraph;
struct ListGraphNode {
int VertexNums, EdgeNums;
HeadNode Head[MAX_NODE_NUMS];
};
ListGraph CreateEmptyGraph(int vertexNums) {
ListGraph graph = (ListGraph)malloc(sizeof(ListGraphNode));
graph->VertexNums = vertexNums;
for(int i = 0; i < graph->VertexNums; i++) {
graph->Head[i].FirstEdge = NULL;
}
return graph;
}
/*注意,这里插入的是有向边*/
void InsertEdge(PToEdge edge, ListGraph graph) {
PToAdjVNode newNode = (PToAdjVNode)malloc(sizeof(AdjVNode));
newNode->Index = edge->End;
newNode->Weight = edge->Weight;
newNode->Next = graph->Head[edge->Start].FirstEdge;
graph->Head[edge->Start].FirstEdge = newNode;
return;
}
ListGraph BuildGraph(int vertexNums, int edgeNums) {
ListGraph graph = CreateEmptyGraph(vertexNums);
graph->EdgeNums = edgeNums;
for(int i = 0; i < edgeNums; i++) {
PToEdge edge = (PToEdge)malloc(sizeof(EdgeNode));
scanf("%d %d %d", &(edge->Start), &(edge->End), &(edge->Weight));
InsertEdge(edge, graph);
free(edge);
}
return graph;
}
int InDegree[MAX_NODE_NUMS];
int Earliest[MAX_NODE_NUMS];
void TopSort(ListGraph graph) {
/*初始化*/
for(int i = 0; i < graph->VertexNums; i++) {
for(PToAdjVNode p = graph->Head[i].FirstEdge; p; p = p->Next) {
InDegree[p->Index]++;
}
}
Queue q = (Queue)malloc(sizeof(QueueNode));
InitQueue(&q);
int Vcount = 0;
for(int i = 0; i < graph->VertexNums; i++) {
if(InDegree[i] == 0) {
Enqueue(&q, i);
Earliest[i] = 0;
}
}
while(!IsEmpty(&q)) {
int vertexIndex = Dequeue(&q);
Vcount++;
for(PToAdjVNode p = graph->Head[vertexIndex].FirstEdge; p; p = p->Next) {
if(Earliest[p->Index] < Earliest[vertexIndex] + p->Weight) {
Earliest[p->Index] = Earliest[vertexIndex] + p->Weight;
}
if(--InDegree[p->Index] == 0) {
Enqueue(&q, p->Index);
}
}
}
if(Vcount != graph->VertexNums) {
printf("Impossible");
}
else {
int max = 0;
for(int i = 0; i < graph->VertexNums; i++) {
if(Earliest[i] > max) {
max = Earliest[i];
}
}
printf("%d", max);
}
}
int main() {
int vertexNums, edgeNums;
scanf("%d %d", &vertexNums, &edgeNums);
ListGraph graph = BuildGraph(vertexNums, edgeNums);
TopSort(graph);
system("pause");
return 0;
}