Gym - 102307G Graduation 拓扑排序

Gym - 102307G  Graduation 

题意:xjl得修够n门课才能毕业,其中有些课是某门课的先行课,并且他精力有限,每学期最多只能修k门课,问xjl最少需要多少学期才能毕业。

首先,正向的图是n对1的,一个点会受到多个点的限制,所以反向建图,这样每去掉一个点,所释放的点都是没有限制的。

解法一:我们以原图中没有入度的点作为深度1,这样新图中没有人度的点就是最高深度,那么如果可以当前选择的点少于等于k个,直接便是取完这些点

那么当多于k个时,根据我们反向的原理自然是让深度高的选取。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1e4+11;
 7 struct Node{
 8     int id,dep;
 9     Node(){}
10     Node(int id,int dep):id(id),dep(dep){}
11     bool operator<(const Node& n1)const{
12         return dep<n1.dep;
13     }
14 };
15 int n,k,ne[N],ra[N];
16 vector<int> vv[N];
17 void dfs(int u){
18     if(vv[u].size()==0){
19         ra[u]=1;
20         return ;
21     }
22     for(int i=0;i<(int)vv[u].size();i++){
23         dfs(vv[u][i]);
24         ra[u]=max(ra[u],ra[vv[u][i]]+1);
25     }
26 }
27 int tp(){
28     queue<int> q;
29     priority_queue<Node> qq;
30     for(int i=1;i<=n;i++) if(!ne[i]) qq.push(Node(i,ra[i]));
31     int ans=0,cnt=0,u,v;
32     while(!qq.empty()){
33         ans++;
34         cnt=0;
35         while(!qq.empty()&&cnt<k){
36             cnt++;
37             q.push(qq.top().id);
38             qq.pop();
39         }
40         while(!q.empty()){
41             u=q.front();
42             q.pop();
43             for(int i=0;(int)i<vv[u].size();i++){
44                 v=vv[u][i];
45                 qq.push(Node(v,ra[v]));
46             }
47         }
48     }
49     return ans;
50 }
51 int main(){
52     while(~scanf("%d%d",&n,&k)){
53         for(int i=0;i<=n;i++) vv[i].clear();
54         for(int i=1;i<=n;i++){
55             scanf("%d",&ne[i]);
56             if(!ne[i]) continue;
57             vv[ne[i]].push_back(i);
58         }
59         for(int i=1;i<=n;i++) if(!ne[i]) dfs(i);
60         printf("%d\n",tp());
61     }
62     return 0;
63 }
nlogn

解法二:每门课的最快能学的学期就取决于它的深度,当某个课被提前学到了 就说明在它的之前可选择的课少于k个,此时直接让那些课便作为一层。

 1 include<cstdio>
 2 #include<vector>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1e4+11;
 7 int n,k,in[N],ne[N],ra[N];
 8 vector<int> vv[N]; 
 9 int tp(){
10     queue<int> q;
11     for(int i=1;i<=n;i++) if(!in[i]){
12         ra[i]=1;
13         q.push(i);
14     }
15     int ans=0,cnt=0,u,v;
16     while(!q.empty()){
17         u=q.front();
18         q.pop();
19         cnt++;
20         if(cnt==1) ans++;
21         if(cnt==k) cnt=0;
22         if(ra[u]>ans) ans++,cnt=1;
23         for(int i=0;i<(int)vv[u].size();i++){
24             v=vv[u][i];
25             ra[v]=max(ra[v],ra[u]+1);
26             in[v]--;
27             if(!in[v]) q.push(v);
28         }
29     }
30     return ans;
31 }
32 int main(){
33     while(~scanf("%d%d",&n,&k)){
34         for(int i=0;i<=n;i++){
35             in[i]=ra[i]=0;
36             vv[i].clear();
37         }
38         for(int i=1;i<=n;i++){
39             scanf("%d",&ne[i]);
40             if(!ne[i]) continue;
41             in[i]++;
42             vv[ne[i]].push_back(i);
43         }
44         printf("%d\n",tp());
45     }
46     return 0;
47 }
48 /*
49 4 2
50 4 4 4 0
51 */
n

 

posted @ 2019-10-14 16:45  新之守护者  阅读(416)  评论(3编辑  收藏  举报