Date:2019-06-17 17:47:15
算法思想
1 //Vi ---- ar ---> Vj 2 3 int e[r]; //活動ar的最早開始時間 4 int l[r]; //活動ar的最晚開始時間 5 int ve[i]; //事件vi的最早發生時間 6 int vl[i]; //事件vi的最晚發生時間 7 8 e[r] = ve[i]; //活動ar的最早開始時間 = 事件vi的最早發生時間 9 l[r] = vl[r]-w[r]; //活動ar的最晚開始時間 = 時間vj的最晚發生時間 - ar的邊權 10 11 12 ve[j] = max{ve[ik] + w[rk]}; //Vj結點的最早發生時間 = Max{前驅結點Vik的最早發生時間+活動aik的邊權} 13 //若解決Vj,必先解決Vi --> 拓撲排序求解ve 14 vl[i] = min(vl[jk] - w[rk]); //Vi結點的最晚發生時間 = Min{后繼結點Vjk的最晚發生時間 - 活動aik的邊權} 15 //若解決Vi,必先解決Vj --> 逆拓撲排序求解vl
算法實現
1 stack<int> topOrder; 2 int TopologicalSort() 3 { 4 queue<int> q; 5 for(int i=0; i<n; i++) 6 if(inDegree[i]==0) 7 q.push(i); 8 while(!q.empty()) 9 { 10 int u = q.front(); 11 q.pop(); 12 topOrder.push(u); //u加入拓撲排序 13 for(int i=0; i<adj[u].size(); i++) 14 { 15 int v = adj[u][i].v; 16 inDegree[v]--; 17 if(inDegree[v]==0) 18 q.push(v); 19 if(ve[u]+adj[u][i].w > ve[v]) 20 ve[v] = ve[u] + adj[u][i].w; //求解ve 21 } 22 } 23 if(topOrder.size() != n) return false; 24 else return true; 25 } 26 27 vector<int> path[M]; //多條關鍵路徑 28 int CriticalPath() 29 { 30 fill(ve, ve+n, 0); 31 if(topologicalSort() == false) 32 return -1; //有環 33 34 int s,t,maxLength=0; 35 for(int i=0; i<n; i++) 36 if(ve[i]==0){ 37 s=i;break; //源點,最早發生的事件 38 } 39 40 for(int i=0; i<n; i++) 41 if(ve[i] > maxLength){ 42 maxLength = ve[i]; 43 t=i; //匯點,最晚發生的事件 44 } 45 fill(vl, vl+n, maxLength); 46 47 while(!topOrder.empty()) 48 { 49 int u = topOrder.top(); 50 topOrder.pop(); 51 for(int i=0; i<adj[u].size(); i++) 52 { 53 int v = adj[u][i].v; 54 if(vl[v] - adj[u][i].w < vl[u]) 55 vl[u] = vl[v] - adj[u][i].w; 56 } 57 } 58 59 for(int u=0; u<n; u++) 60 { 61 for(int i=0; i<adj[u].size(); i++) 62 { 63 int v = adj[u][i].v; 64 int w = adj[u][i].w; 65 int e = ve[u]; //活動的最早開始時間 66 int l = vl[v]-w; //活動的最晚開始時間 67 if(e==l) 68 path[u].push_back(v); 69 } 70 } 71 72 printf("%d", s); 73 s=path[s][0]; 74 while(s != t) 75 { 76 printf("->%d",s); //輸出一條關鍵路徑 77 s=path[s][0]; 78 } 79 80 return ve[t]; //返回關鍵路徑長度 81 }
相關練習
- 更新后的大綱把動態規划都刪除了,但關鍵路徑還留着,雖然一直沒考過,說不准哪天就考了呢。
Source:
題目描述
描述:
圖的連接邊上的數據表示其權值,帶權值的圖稱作網。
上圖可描述為頂點集為(a,b,c,d,e)
邊集及其權值為(始點,終點 權值):
a b 3
a c 2
b d 5
c d 7
c e 4
d e 6
網的源點是入度為0的頂點,匯點是出度為0的頂點。網的關鍵路徑是指從源點到匯點的所有路徑中,具有最大路徑長度的路徑。上圖中的關鍵路徑為a->c->d->e,其權值之和為關鍵路徑的長度為15。
本題的要求是根據給出的網的鄰接矩陣求該網的關鍵路徑及其長度。
輸入
第一行輸入一個正整數n(1<=n<=5),其代表測試數據數目,即圖的數目
第二行輸入x(1<=x<=15)代表頂點個數,y(1<=y<=19)代表邊的條數
第三行給出圖中的頂點集,共x個小寫字母表示頂點
接下來每行給出一條邊的始點和終點及其權值,用空格相隔,每行代表一條邊。
輸出
第一個輸出是圖的關鍵路徑(用給出的字母表示頂點, 用括號將邊括起來,頂點逗號相隔)
第二個輸出是關鍵路徑的長度
每個矩陣對應上面兩個輸出,兩個輸出在同一行用空格間隔,每個矩陣的輸出占一行。
樣例輸入
2
5 6
abcde
a b 3
a c 2
b d 5
c d 7
c e 4
d e 6
4 5
abcd
a b 2
a c 3
a d 4
b d 1
c d 3
樣例輸出
(a,c) (c,d) (d,e) 15
(a,c) (c,d) 6
Code:
1 #include<cstdio> 2 #include<map> 3 #include<stack> 4 #include<queue> 5 #include<vector> 6 #include<algorithm> 7 using namespace std; 8 const int M=1e2; 9 struct node 10 { 11 int v,w; 12 }; 13 map<char,int> mp; 14 stack<int> topOrder; 15 vector<node> adj[M]; 16 vector<int> path[M]; 17 int k,n,m,inDegree[M],ve[M],vl[M]; 18 char str[M]; 19 20 void TopologicalSort() 21 { 22 queue<int> q; 23 for(int i=0; i<n; i++) 24 if(inDegree[i]==0) 25 q.push(i); 26 while(!q.empty()) 27 { 28 int u = q.front();q.pop(); 29 topOrder.push(u); 30 for(int i=0; i<adj[u].size(); i++) 31 { 32 int v = adj[u][i].v; 33 inDegree[v]--; 34 if(inDegree[v]==0) 35 q.push(v); 36 if(ve[u]+adj[u][i].w > ve[v]) 37 ve[v] = ve[u] + adj[u][i].w; 38 } 39 } 40 } 41 42 int CriticalPath() 43 { 44 fill(ve,ve+n,0); 45 TopologicalSort(); 46 47 int s,t,maxLength=0; 48 for(int i=0; i<n; i++) 49 if(ve[i]==0){ 50 s=i;break; 51 } 52 for(int i=0; i<n; i++) 53 if(ve[i]>maxLength){ 54 maxLength=ve[i]; 55 t=i; 56 } 57 fill(vl,vl+n,maxLength); 58 59 while(!topOrder.empty()) 60 { 61 int u = topOrder.top(); 62 topOrder.pop(); 63 for(int i=0; i<adj[u].size(); i++) 64 { 65 int v = adj[u][i].v; 66 if(vl[v]-adj[u][i].w < vl[u]) 67 vl[u] = vl[v]-adj[u][i].w; 68 } 69 } 70 71 for(int u=0; u<n; u++) 72 { 73 for(int i=0; i<adj[u].size(); i++) 74 { 75 int v=adj[u][i].v; 76 int w=adj[u][i].w; 77 int e=ve[u]; 78 int l=vl[v]-w; 79 if(e==l) 80 path[u].push_back(v); 81 } 82 } 83 84 while(s != t) 85 { 86 printf("(%c,%c) ", str[s],str[path[s][0]]); 87 s=path[s][0]; 88 } 89 printf("%d\n", ve[t]); 90 } 91 92 int main() 93 { 94 #ifdef ONLINE_JUDGE 95 #else 96 freopen("Test.txt", "r", stdin); 97 #endif // ONLINE_JUDGE 98 99 scanf("%d", &k); 100 while(k--) 101 { 102 scanf("%d%d\n", &n,&m); 103 scanf("%s\n", str); 104 105 mp.clear(); 106 fill(inDegree,inDegree+M,0); 107 for(int i=0; i<n; i++) 108 { 109 adj[i].clear(); 110 path[i].clear(); 111 } 112 113 for(int i=0; i<n; i++) 114 mp[str[i]]=i; 115 for(int i=0; i<m; i++) 116 { 117 int c1,c2,w; 118 scanf("%c %c %d\n", &c1,&c2,&w); 119 int v1=mp[c1], v2=mp[c2]; 120 adj[v1].push_back(node{v2,w}); 121 inDegree[v2]++; 122 } 123 CriticalPath(); 124 } 125 126 return 0; 127 }
