好长时间没写博客了,真心惭愧啊!
废话少说,原题链接:https://pta.patest.cn/pta/test/1342/exam/4/question/24939
题目如下:
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 NNN (≤100le 100≤100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1N-1N−1), and MMM, the number of activities. Then MMM 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
这道题不难,本质上就是一道拓扑排序的问题,只不过增加了权重,成为了一道关键路径的问题,此类拓扑排序问题的核心思想就是先在图中找到入度为0的点,对其进行操作,然后将于该点相邻的边删除,继续对剩下的图重复这一过程。为了提高算法的效率,陈越老师讲过可以在每次删除边时,检查其它顶点是否入度为0,如果为0就将其放在一个容器里面(我用的是队列),下次用的时候就可以直接从容器里面取出。拓扑排序一般是较为稀疏的图,应该用邻接表存储图合适,但我为了写起来简单,就用了邻接矩阵。以下是我的代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<stdbool.h> 4 #define Max 105 5 #define INFINITY 65535 6 typedef struct QNode{ 7 int front,rear; 8 int Data[Max]; 9 int Maxsize; 10 }Quenue; 11 12 Quenue *CreateQ(int N) 13 { 14 Quenue *Q=(Quenue *)malloc(sizeof(struct QNode)); 15 Q->front=Q->rear=0; 16 Q->Maxsize=N+1; 17 return Q; 18 } 19 20 bool IsFull(Quenue *Q) 21 { 22 return ((Q->front+1)%Q->Maxsize == Q->rear); 23 } 24 25 void Push(Quenue *Q,int v) 26 { 27 if (!IsFull(Q)) 28 { 29 Q->front=(Q->front+1)%Q->Maxsize; 30 Q->Data[Q->front]=v; 31 } 32 } 33 34 bool IsEmpty(Quenue *Q) 35 { 36 return (Q->front==Q->rear); 37 } 38 39 int Pop(Quenue *Q) 40 { 41 if (!IsEmpty(Q)) 42 { 43 Q->rear=(Q->rear+1)%Q->Maxsize; 44 return (Q->Data[Q->rear]); 45 } 46 } 47 48 int G[Max][Max]; 49 int N,M; 50 51 52 void TopSort() 53 { 54 int Indegree[Max]={0}; 55 int v,w,weight,cnt=0; 56 int endcnt=0; //有多个终点是,用来记录是否为终点的变量 57 int dist[Max]={0}; 58 Quenue *Q=CreateQ(N); 59 /* 初始化各顶点的入度值 */ 60 for (v=0;v<N;v++) 61 { 62 for (w=0;w<N;w++) 63 { 64 if ( G[w][v]<INFINITY)Indegree[v]++; 65 } 66 } 67 /*入度为0的顶点入队 */ 68 for (v=0;v<N;v++) 69 { 70 if (Indegree[v]==0){Push(Q,v);} 71 } 72 /*拓扑排序*/ 73 weight=0; 74 while (!IsEmpty(Q)) 75 { 76 v=Pop(Q); 77 cnt++; 78 for (w=0;w<N;w++) 79 { 80 if (G[v][w]<INFINITY) 81 { 82 if (dist[v]+G[v][w]>dist[w])dist[w]=dist[v]+G[v][w]; 83 if (--Indegree[w]==0)Push(Q,w); 84 endcnt++; 85 } 86 } 87 if (endcnt==0) //此时v为终点 88 { 89 if (dist[v]>weight)weight=dist[v]; 90 } 91 endcnt=0; 92 } 93 if (cnt!=N)printf("Impossible"); 94 else printf("%d",weight); 95 return ; 96 } 97 98 int main() 99 { 100 scanf("%d %d",&N, &M); 101 int i,j,v,w,weight; 102 for (i=0;i<N;i++){ 103 for (j=0;j<N;j++){G[i][j]=INFINITY;}} 104 for (i=0;i<M;i++) 105 { 106 scanf("%d %d %d",&v, &w, &weight); 107 G[v][w]=weight; 108 } 109 TopSort(); 110 return 0; 111 }