浙大数据结构第八周之08-图8 How Long Does It Take

前置知识:

拓扑排序:

/* 邻接表存储 - 拓扑排序算法 */

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.

Input Specification:

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.

Output Specification:

For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output "Impossible".

Sample Input 1:

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

Sample Output 1:

18

Sample Input 2:

4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5

Sample Output 2:

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;
}                                                                                                                   

你可能感兴趣的:(数据结构,数据结构)