洛谷 P1983 车站分级 巧妙拓扑排序

洛谷 P1983 车站分级 巧妙拓扑排序

题解:

题目的意思是让我们找出一个最大的车站分级,满足对所有的车次,有:
如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。也就是说,这趟车次经过且不停靠的所有车站的级别都必须小于这趟车次停靠的所有车站的级别。
等级较低的车站不用停靠的车站,由等级低的车站等级高的车站连一条边,然后利用拓扑排序,满足这些关系。在拓扑排序的过程中,我们只要求出最大的层数即可。

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<map>
#define MAX 1005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,m,x;//n个车站,m趟车次
//s[i][0]为第i趟列车停靠车站的数量,mp[][]为建立的图,in记录入度
//visit[i]表示第i站为停靠的站
int s[MAX][MAX],flag[MAX][MAX],in[MAX],visit[MAX];
vector<int> adj[MAX];
typedef pair<int,int> p;

int topo(){
    int maxl=1;
    queue<p> q;//队列中的每个元素有2个关键字,第一个是车站编号,第二个是级别
    for(int i=1;i<=n;i++){
        if(in[i]==0){
            q.push(p(i,1));//没有入度,级别最低,最低为1
        }
    }
    while(!q.empty()){
        p top=q.front();
        int u=top.first,ans=top.second;//u为当前的车站编号,ans为级别
        q.pop();
        for(int i=0;i<adj[u].size();i++){
            int v=adj[u][i];
            in[v]--;
            if(in[v]==0){
                q.push(p(v,ans+1));//递推,当前点的级别为ans+1
                maxl=max(maxl,ans+1);//maxl记录最高级别,也就是不同级别的数量
            }
        }
    }
    return maxl;
}


int main(){
    scanf("%d%d",&n,&m);
    memset(flag,0,sizeof(flag));//初始化mp
    for(int i=1;i<=m;i++){
        scanf("%d",&s[i][0]);
        memset(visit,0,sizeof(visit));
        for(int j=1;j<=s[i][0];j++){
            scanf("%d",&x);
            s[i][j]=x;//存储第i趟车停靠的站
            visit[x]=1;//当前车次有停靠在x车站
        }
        for(int j=s[i][1];j<=s[i][s[i][0]];j++){//从始发站到终点站
            if(visit[j]) continue;//这条路上所有不停靠的必须比所有停靠的级别低
            for(int k=1;k<=s[i][0];k++){//这时候的j是没有停靠的车站
                if(flag[j][s[i][k]]==0){//有向边由不停靠的车站指向停靠的车站
                    in[s[i][k]]++;//入度+1
                    adj[j].push_back(s[i][k]);
                   //j向s[i][k]连边,表示j的级别必须比s[i][k]低
                    flag[j][s[i][k]]=1;//标记为连过的边
                }
            }
        }
    }
    int res=topo();//拓扑排序
    printf("%d",res);
    return 0;
}
发布了253 篇原创文章 · 获赞 15 · 访问量 7967

猜你喜欢

转载自blog.csdn.net/weixin_44123362/article/details/104055592