P1113 雜務https://www.luogu.org/problemnew/show/P1113
題目描述
John的農場在給奶牛擠奶前有很多雜務要完成,每一項雜務都需要一定的時間來完成它。比如:他們要将奶牛集合起來,将他們趕進牛棚,為奶牛清洗乳房以及一些其它工作。盡早将所有雜務完成是必要的,因為這樣才有更多時間擠出更多的牛奶。當然,有些雜務必須在另一些雜務完成的情況下才能進行。比如:隻有将奶牛趕進牛棚才能開始為它清洗乳房,還有在未給奶牛清洗乳房之前不能擠奶。我們把這些工作稱為完成本項工作的準備工作。至少有一項雜務不要求有準備工作,這個可以最早着手完成的工作,标記為雜務1。John有需要完成的n個雜務的清單,并且這份清單是有一定順序的,雜務k(k>1)的準備工作隻可能在雜務1..k-1中。
寫一個程式從1到n讀入每個雜務的工作說明。計算出所有雜務都被完成的最短時間。當然互相沒有關系的雜務可以同時工作,并且,你可以假定John的農場有足夠多的勞工來同時完成任意多項任務。
輸入輸出格式
輸入格式:
第1行:一個整數n,必須完成的雜務的數目(3<=n<=10,000);
第2 ~ n+1行: 共有n行,每行有一些用1個空格隔開的整數,分别表示:
* 工作序号(1..n,在輸入檔案中是有序的);
* 完成工作所需要的時間len(1<=len<=100);
* 一些必須完成的準備工作,總數不超過100個,由一個數字0結束。有些雜務沒有需要準備的工作隻描述一個單獨的0,整個輸入檔案中不會出現多餘的空格。
輸出格式:
一個整數,表示完成所有雜務所需的最短時間。
輸入輸出樣例
輸入樣例#1:
7
1 5 0
2 2 1 0
3 3 2 0
4 6 1 0
5 1 2 4 0
6 8 2 4 0
7 4 3 5 6 0
輸出樣例#1:
23
題目分析:就是求關鍵路徑,并且由題目易知不會出現環等無解的情況并且隻是要求值,不需要求路徑經過的點,是以可以直接通過一次拓撲排序來解決【如果要求出關鍵路徑還需要逆拓撲排序】
1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 #include<cstring>
5 #include<queue>
6 using namespace std;
7 vector<int>vs[10005];//記錄本點工作完成之後的工作點
8 queue<int>pq;
9 int qwq[10005];//完成某一工作所需的時間
10 int dist[10005];//記錄工作的最早時間
11 int out[10005];//出度
12 int in[10005];//入度
13 int ans=0;
14 void topu()
15 {
16 while(!pq.empty())
17 {
18 int t=pq.front();pq.pop();
19 for(int i = 0 ; i< vs[t].size() ; i++)
20 {
21 in[vs[t][i]]--;
22 dist[vs[t][i]]=max(dist[vs[t][i]],qwq[vs[t][i]]+dist[t]);//更新點的最早時間
23 if(!in[vs[t][i]])
24 {
25 if(out[vs[t][i]])//核心,出度不為0時将點放進隊列
26 pq.push(vs[t][i]);
27 else
28 ans=max(ans,dist[vs[t][i]]);//核心,如果出度為0,就對最後結果進行更新
29 }
30 }
31 }
32 }
33 int main()
34 {
35 int n;
36 scanf("%d",&n);
37 memset(dist,0,sizeof(dist));
38 for(int i = 1 ; i <= n ;i++)
39 {
40 int a,b;
41 scanf("%d",&a);
42 scanf("%d",&qwq[a]);
43 int x;
44 scanf("%d",&x);
45 while(x)
46 {
47 in[a]++;
48 out[x]++;
49 vs[x].push_back(a);
50 scanf("%d",&x);
51 }
52 }
53 for(int i = 1 ; i <= n ; i++)
54 {
55 if(!in[i]){
56 dist[i]=qwq[i];
57 pq.push(i);
58 }
59 }
60 topu();
61 cout << ans << endl;
62 return 0;
63 }
轉載于:https://www.cnblogs.com/MekakuCityActor/p/9005169.html