【NOIP2013】【Luogu1983】车站分级(建图,拓扑排序)

problem

  • 给定n个车站(依次编号从1到n,并且有一个优先级),m趟车次(每次停靠的站点)
  • 满足每一趟车次中,如果停靠了x,那么这一趟车次中所有优先级>=x的都要停。(始发站和终点站自然也要停另说)
  • 求最少有多少个优先级。

solution

  • 因为所有>=x的都要停,所以没停的都是优先级小于x的,即一趟车次中没停的站点的优先级要小于这趟车次的每一个停靠站。(因为这一趟车次停靠站之间的相对大小不知道,不能拿那个算。)
  • 于是就可以得到车站之间的大小关系。从小的(所有没停的)向大的(所有停了的)都连一条边。拓扑排序统计有几层(开pair加一而不是节点遇到入度0的原因是入度相同的节点可能不唯一,他们可以是一个层级的,就会有重复统计的问题)。

codes

#include
#include
#include
#include
#include
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
    queueint, 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<'\n';
    return 0;
}

转载于:https://www.cnblogs.com/gwj1314/p/9444622.html

你可能感兴趣的:(【NOIP2013】【Luogu1983】车站分级(建图,拓扑排序))