1. 程式人生 > >題解:車站分級(2013普及組)

題解:車站分級(2013普及組)

這道題可以暴力可以拓撲排序

甚至還可以差分約束????

原諒我一開始沒看出來可以差分約束

這是暴力做法

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int f[1010][1010], a[1010];//f陣列記錄每趟車次停靠的站點,a陣列記第i個車站的分級
 6 bool by[1010][1010];//表示第i趟車是否在j站停靠,true表示停靠
 7 int n, m, maxn;
 8 int main(){
9 cin>>n>>m; 10 memset(by,false,sizeof(by)); 11 for(int i=1; i<=n; i++){ 12 a[i]=1; 13 } 14 for(int i=1; i<=m; i++){ 15 cin>>f[i][0]; 16 for(int j=1; j<=f[i][0]; j++){ 17 cin>>f[i][j]; 18 by[i][f[i][j]]=true
; 19 } 20 } 21 while(1){ 22 bool judge=false; 23 for(int i=1; i<=m; i++){ 24 maxn=0; 25 for(int j=f[i][1]; j<=f[i][f[i][0]]; j++){ 26 if(by[i][j]==false) maxn=max(a[j], maxn);//記錄不停靠的最大值 27 } 28 maxn++;//停靠的一定比不停靠的至少打1
29 for(int j=1; j<=f[i][0]; j++){ 30 if(a[f[i][j]]<maxn){ 31 a[f[i][j]]=maxn; 32 judge=true; 33 } 34 } 35 } 36 if(!judge) break;//沒有更新過就跳出 37 } 38 maxn=0; 39 for(int i=1; i<=n; i++){ 40 maxn=max(a[i],maxn); 41 } 42 cout<<maxn<<endl; 43 return 0; 44 }

這是拓撲的做法

把沒有停靠過的車站連一條有向邊到停靠過的車站。沒有停靠過的從下面向上指向停靠過的,等級比上面的低。

那麼每有一層就代表有一個等級,不斷地斷邊,每斷掉一層就ans++

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int s[1005], degree[1005], topo[1005];//s記錄停靠的車站,degree表示類似於入度的東西,topo為記錄陣列
 6 bool is[1005], edge[1005][1005], vis[1005];//is表示是否停靠,edge表示是否從i到j連邊, vis表示是否在topo數組裡
 7 int n, m, ans, top;
 8 int main(){
 9     cin>>n>>m;
10     for(int i=1; i<=m; i++){
11         memset(is, false, sizeof(is));
12         cin>>s[0];
13         for(int j=1; j<=s[0]; j++){
14             cin>>s[j];
15             is[s[j]]=true;
16         }
17         for(int j=s[1]; j<=s[s[0]]; j++){
18             if(!is[j]){
19                 for(int k=1; k<=s[0]; k++){
20                     if(!edge[j][s[k]]){
21                         edge[j][s[k]]=true;
22                         degree[s[k]]++;
23                     }
24                 }
25             }
26         }
27     }
28     do{
29         top=0;
30         for(int i=1; i<=n; i++){
31             if(!degree[i] && !vis[i]){
32                 topo[++top]=i;
33                 vis[i]=true;
34             }
35         }
36         for(int i=1; i<=top; i++){
37             for(int j=1; j<=n; j++){
38                 if(edge[topo[i]][j]){
39                     edge[topo[i]][j]=false;
40                     degree[j]--;
41                 }
42             }
43         }
44         ans++;
45     }while(top);
46     --ans;
47     cout<<ans<<endl;
48     return 0;
49 }