7-11 關鍵活動(30 分)
假定一個工程項目由一組子任務構成,子任務之間有的能夠並行執行,有的必須在完成了其它一些子任務後才能執行。「任務調度」包括一組子任務、以及每一個子任務能夠執行所依賴的子任務集。數組
好比完成一個專業的全部課程學習和畢業設計能夠當作一個本科生要完成的一項工程,各門課程能夠當作是子任務。有些課程能夠同時開設,好比英語和C程序設計,它們沒有必須先修哪門的約束;有些課程則不能夠同時開設,由於它們有前後的依賴關係,好比C程序設計和數據結構兩門課,必須先學習前者。數據結構
可是須要注意的是,對一組子任務,並非任意的任務調度都是一個可行的方案。好比方案中存在「子任務A依賴於子任務B,子任務B依賴於子任務C,子任務C又依賴於子任務A」,那麼這三個任務哪一個都不能先執行,這就是一個不可行的方案。學習
任務調度問題中,若是還給出了完成每一個子任務須要的時間,則咱們能夠算出完成整個工程須要的最短期。在這些子任務中,有些任務即便推遲幾天完成,也不會影響全局的工期;可是有些任務必須準時完成,不然整個項目的工期就要所以延誤,這種任務就叫「關鍵活動」。spa
請編寫程序斷定一個給定的工程項目的任務調度是否可行;若是該調度方案可行,則計算完成整個工程項目須要的最短期,並輸出全部的關鍵活動。設計
輸入格式:
輸入第1行給出兩個正整數N(≤100)和M,其中N是任務交接點(即銜接相互依賴的兩個子任務的節點,例如:若任務2要在任務1完成後纔開始,則兩任務之間必有一個交接點)的數量。交接點按1~N編號,M是子任務的數量,依次編號爲1~M。隨後M行,每行給出了3個正整數,分別是該任務開始和完成涉及的交接點編號以及該任務所需的時間,整數間用空格分隔。code
輸出格式:
若是任務調度不可行,則輸出0;不然第1行輸出完成整個工程項目須要的時間,第2行開始輸出全部關鍵活動,每一個關鍵活動佔一行,按格式「V->W」輸出,其中V和W爲該任務開始和完成涉及的交接點編號。關鍵活動輸出的順序規則是:任務開始的交接點編號小者優先,起點編號相同時,與輸入時任務的順序相反。blog
輸入樣例:
7 8 1 2 4 1 3 3 2 4 5 3 4 3 4 5 1 4 6 6 5 7 5 6 7 2
輸出樣例:
解題思路:這題基本上是基於拓撲排序的。此外還定義了一個最先發生時間的數組,從1循環到n;一個最遲發生時間,逆向循環
17 1->2 2->4 4->6 6->7
1 early[i] = FindMax( early[i],early[temp]+G[temp][i] ); 2 3 late[i] = FindMin( late[i],late[temp]-G[i][temp] );
這裏要注意的是最先發生時間是求幾個路線的最大數,最遲發生時間是求最小數排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 #define MAXVER 105 5 #define INFINITY 65535 6 7 int G[MAXVER][MAXVER]; //圖 8 int early[MAXVER]; //最先發生時間 9 int late[MAXVER]; //最遲發生時間 10 int in[MAXVER]; //入度 11 int out[MAXVER]; //出度 12 int nv,ne; //頂點數目 ,邊數目 13 14 void CreatGraph(); 15 int EarlyTime(); 16 void LateTime(int Scost); 17 int FindMax( int a,int b); 18 int FindMin( int a,int b); 19 20 int main() 21 { 22 int flag; 23 int i,j; 24 scanf("%d %d",&nv,&ne); 25 26 CreatGraph(); 27 flag = EarlyTime(); 28 if( flag==-1) 29 { 30 printf("0\n"); 31 } 32 else 33 { 34 printf("%d\n",flag); 35 LateTime( flag ); 36 for( i=1; i<=nv; i++) 37 { 38 if(early[i] != late[i]) 39 continue; 40 for( j=nv; j>=1 ; j--) 41 { 42 if( G[i][j]>=0 && early[j]==late[j] &&late[j]-G[i][j]==early[i]) 43 { 44 //i,j均在關鍵路徑上且相鄰 45 printf("%d->%d\n",i,j); 46 } 47 } 48 } 49 50 } 51 return 0; 52 } 53 54 void CreatGraph() 55 { 56 int i,j; 57 int s,d,cost; 58 59 for( i=1; i<=nv; i++) 60 { 61 for( j=1; j<=nv; j++) 62 { 63 G[i][j] = -1; 64 } 65 early[i] = 0; 66 late[i] = INFINITY; 67 in[i] = 0; 68 out[i] = 0; 69 } 70 for( i=0; i<ne; i++) 71 { 72 scanf("%d %d %d",&s,&d,&cost); 73 G[s][d] = cost; //有向邊 74 in[d] ++; 75 out[s]++; 76 } 77 78 } 79 80 int EarlyTime() 81 { 82 int queue[nv]; 83 int first =-1,rear = -1; 84 int count=0; 85 int i; 86 int temp,ret=0; 87 88 for( i=1; i<=nv; i++) 89 { 90 if( in[i]==0) 91 { 92 //若是入度爲0則入隊 93 queue[++rear] = i; 94 } 95 } 96 97 while( first<rear) //判斷隊是否爲空 98 { 99 temp = queue[++first]; //出隊 100 count++; 101 for( i=1; i<=nv; i++) 102 { 103 if( G[temp][i]>=0 ) 104 { 105 in[i]--; 106 early[i] = FindMax( early[i],early[temp]+G[temp][i]); 107 if( in[i]==0) 108 { 109 queue[++rear] = i; 110 } 111 } 112 } 113 } 114 if( count!=nv) 115 { 116 ret = -1; 117 } 118 else 119 { 120 ret = early[1]; 121 for( i=2; i<=nv; i++) 122 { 123 if(early[i] > ret) 124 { 125 //找出最大的early[i] 126 ret = early[i]; 127 } 128 } 129 } 130 131 return ret; 132 } 133 134 void LateTime(int Scost) 135 { 136 int i; 137 int queue[MAXVER]; 138 int first=-1,rear=-1; 139 int temp; 140 141 for( i=1; i<=nv; i++) 142 { 143 if( out[i]==0) 144 { 145 queue[++rear] = i; 146 late[i] = Scost; 147 } 148 } 149 150 while( first<rear ) 151 { 152 temp = queue[++first]; 153 for( i=nv; i>=1; i--) 154 { 155 if( G[i][temp]>=0) 156 { 157 late[i] = FindMin( late[i],late[temp]-G[i][temp]); 158 out[i]--; 159 if(out[i]==0) 160 { 161 queue[++rear] = i; 162 } 163 } 164 } 165 166 } 167 168 } 169 int FindMax( int a,int b) 170 { 171 if( a>b ) 172 { 173 return a; 174 } 175 else 176 { 177 return b; 178 } 179 } 180 int FindMin( int a,int b) 181 { 182 if( a>b ) 183 { 184 return b; 185 } 186 else 187 { 188 return a; 189 } 190 }
PS:做爲一個剛剛接觸的渣渣,我以爲這道題有點難,作了好久,實在沒思路的話就跳過吧io