How Long Does It Take

好长时间没写博客了,真心惭愧啊!

废话少说,原题链接: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 (≤100\le 100100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1N-1N1), 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 }

 

posted @ 2016-11-20 17:01  变通无敌  阅读(473)  评论(0编辑  收藏  举报