天天看點

【拓撲排序】【關鍵路徑】 P1113 雜務https://www.luogu.org/problemnew/show/P1113題目描述

 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