LuoguP1983车站分级

题目描述:一条单向的铁路线上,依次有编号为1 - n的n个火车站,有m趟车次。每个火车站都有一个级别,最低为1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站x,则始发站、终点站之间所有级别大于等于火车站x的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)。1≤n,m≤1000。

停靠的车站等级大于未停靠的车站,有点类似于差分约束系统,于是很容易用图论。将每一车次停靠的车站向始发站和终点站之间没有停靠的车站连一条有向边,拓扑排序 + DP即可。r[i]表示某趟车次中在车站i停靠,t[i]保存某趟车次停靠的车站,in[i]记录车站i的入度,dp[i]车站i的等级,按照题目中的描述,1为最低等级,显然等级越高dp值应越高,但由于让我们求最大的等级,所以这里将其倒过来,即1为最高等级,求出最大的dp值即为答案。

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm> 
#define N 1001
using namespace std;
int G[N][N],in[N],dp[N],r[N],t[N],n,m,ans;
void solve(){
    //TopologicalSort
    queue<int> Q;
    for(int i = 1;i <= n;i++){
        if(!in[i]){
            Q.push(i);
            dp[i] = 1;
        }
    }
    while(!Q.empty()){
        int u = Q.front();Q.pop();
        for(int v = 1;v <= n;v++){
            if(G[u][v]){
                if(!(--in[v])) Q.push(v);
                dp[v] = max(dp[v],dp[u] + 1);
                ans = max(dp[v],ans);
            }
        }
    }
    printf("%d
",ans);
}
int main(){
    cin>>n>>m;
    for(int i = 1;i <= m;i++){
        memset(r,0,sizeof(r));
        int all;
        scanf("%d",&all);
        for(int j = 1;j <= all;j++){
            scanf("%d",&t[j]);
            r[t[j]] = 1;
        }
        for(int j = 1;j <= all;j++){
            for(int k = t[1] + 1;k < t[all];k++)
            {
                if(!r[k] && !G[t[j]][k]){
                    G[t[j]][k] = 1;
                    in[k]++;
                }
            }
        }
    }
    solve();
    return 0;
}
岂能尽如人意,但求无愧我心
原文地址:https://www.cnblogs.com/Zforw/p/10541962.html