題解:車站分級(2013普及組)
阿新 • • 發佈:2018-11-02
這道題可以暴力可以拓撲排序
甚至還可以差分約束????
原諒我一開始沒看出來可以差分約束
這是暴力做法
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++;//停靠的一定比不停靠的至少打129 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 }