拓扑排序以及队列栈的使用 (车站分级noip2013第四题)

问题描述

一条单向的铁路线上,依次有编号为 1, 2, …, n 的 n 个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)例如,下表是 5 趟车次的运行情况。其中,前 4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。
 

现有 m 趟车次的运行情况(全部满足要求) ,试推算这 n 个火车站至少分为几个不同的级别。

        输入

第一行包含 2 个正整数 n, m,用一个空格隔开。第 i + 1 行(1 ≤ i ≤ m)中,首先是一个正整数 si (2 ≤ si≤ n),表示第 i 趟车次有 si 个停靠站;接下来有 si 个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。

输入样例#1:
Case 1:
9 2 
4 1 3 5 6 
3 3 5 6 

Case 2:
9 3 
4 1 3 5 6 
3 3 5 6 
3 1 5 9 
输出样例#1:
Case 1:
2

Case 2:
3
根据题意,可以知道,一个列车没有经过的点的分级的值都是要比自己的值要小的,于是给每一个没有经过的点和经过的点连一条有向边,运用拓扑排序的知识,找到入度为0的点,并且删除与其相连的所有边,我们可以用栈或者队列来储存时间戳也就是ans的值,这道题细节比较多,很多地方还是值得细细考虑的。
 1 #include<bits/stdc++.h>
 2 #define maxn 1100
 3 using namespace std;
 4 int book[maxn][maxn],du[maxn];
 5 int n,m,x,y;
 6 int ans=0;
 7 int s[maxn];
 8 int judge[maxn];
 9 
10 
11 void topusort()
12 {
13     int num=0;
14     queue<int > q;    
15     
16     while(num<n)
17     {        
18         for(int i=1;i<=n;i++)
19           if(du[i]==0)
20           {
21               du[i]=-1;     
22               q.push(i);
23               num++; 
24           }
25           ans++;
26           while(!q.empty())
27           {
28              int k=q.front();q.pop();
29              for(int j=1;j<=n;j++)
30                     if(book[k][j]==1)
31                     {
32                        book[k][j]=0;
33                        du[j]--;
34                    }
35           }           
36       }
37 }
38 
39 
40 void init()
41 {
42    cin>>n>>m;
43    
44    while(m--)
45    {
46          int x;
47          memset(judge,0,sizeof(judge));
48          cin>>x;
49          for(int i=1;i<=x;i++)
50          {
51             cin>>s[i];
52             judge[s[i]]++;
53 
54         }
55         for(int i=s[1];i<=s[x];i++)
56            if(!judge[i])
57            {
58                for(int j=1;j<=x;j++)
59                  book[i][s[j]]=1;        
60              }
61    }
62    for(int i=1;i<=n;i++)
63        for(int j=1;j<=n;j++)
64        if(book[i][j])              
65            du[j]++;
66 }
67 
68 void output()
69 {
70     cout<<ans<<endl;
71 }
72 
73 int main()
74 {
75       ios::sync_with_stdio(false);
76       init();
77       topusort();
78       output();
79     return 0;
80 }

 


总结:1.stl跑的慢不要随意使用max or min,性能差一个档次.
2.ios::sync_with_stdio(false);一旦你用cin,cout这句话无论如何都要加上,否则必须得用scanf printf或者其他的读入优化
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值