1. 程式人生 > >【NOIP2013】【Luogu1983】車站分級(建圖,拓撲排序)

【NOIP2013】【Luogu1983】車站分級(建圖,拓撲排序)

problem

  • 給定n個車站(依次編號從1到n,並且有一個優先順序),m趟車次(每次停靠的站點)
  • 滿足每一趟車次中,如果停靠了x,那麼這一趟車次中所有優先順序>=x的都要停。(始發站和終點站自然也要停另說)
  • 求最少有多少個優先順序。

solution

  • 因為所有>=x的都要停,所以沒停的都是優先順序小於x的,即一趟車次中沒停的站點的優先順序要小於這趟車次的每一個停靠站。(因為這一趟車次停靠站之間的相對大小不知道,不能拿那個算。)
  • 於是就可以得到車站之間的大小關係。從小的(所有沒停的)向大的(所有停了的)都連一條邊。拓撲排序統計有幾層(開pair加一而不是節點遇到入度0的原因是入度相同的節點可能不唯一,他們可以是一個層級的,就會有重複統計的問題)。

codes

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1010;
int ting[maxn], vis[maxn];
vector<int>G[maxn]; int in[maxn]; int book[maxn][maxn];
int main(){
    int n, m;  cin>>n>>m;
    for
(int i = 1; i <= m; i++){ memset(vis,0,sizeof(vis)); int x; cin>>x; for(int j = 1; j <= x; j++){ cin>>ting[j]; vis[ting[j]]=1;} for(int j = ting[1]; j <= ting[x]; j++){//按照順序的,開始站到終點站之間的每一個站 if(vis[j])continue;//列舉沒停的 for(int k = 1
; k <= x; k++)//列舉停了的 {//連一條邊 if(book[j][ting[k]])continue;//判重優化時間 else book[j][ting[k]] = 1; G[j].push_back(ting[k]); in[ting[k]]++; } } } int ans = 1; //topusort queue<pair<int, int> >q; for(int i = 1; i <= n; i++)if(in[i]==0)q.push(make_pair(i,1));//入度為0 while(q.size()){ int u = q.front().first, v = q.front().second; q.pop(); for(int i = 0; i < G[u].size(); i++) if(--in[G[u][i]] == 0){q.push(make_pair(G[u][i],v+1));ans = max(ans,v+1);} } cout<<ans<<'\n'; return 0; }