洛谷题单指南-图的基本应用-P1983 [NOIP2013 普及组] 车站分级

原题链接:https://www.luogu.com.cn/problem/P1983

题意解读:由于“如果这趟车次停靠了火车站,则始发站、终点站之间所有级别大于等于火车站的都必须停靠”。因此,在始发站和终点站之间,能停靠的车站都是级别较高的,没有停靠的车站都是级别较低的,计算最少有多少个不同级别。

解题思路:

有若干车站可以是同一个级别,如未停靠的车站都可以设置同样的低级别,停靠的车站根据相关关系也可以划分不同的级别,可以通过建图形成层级关系。

由于停靠的车站都是级别较高的,未停靠的车站都是级别较低的,所以对于起点、终点之间每一个未停靠的车站,可以建立一条指向停靠车站的边

对样例进行模拟

9 2 
4 1 3 5 6 
3 3 5 6

图中2、4是未停靠站,可以设定同样的级别,1、3、5、6是停靠站,也可以设定同样的级别,因此一共只需要2个级别。

在图形结构中,2、4是拓扑排序的第一层,1、3、5、6是拓扑排序的第二层。

有了这个设想,在用另外一个样例进行模拟,验证是否正确

9 3 
4 1 3 5 6 
3 3 5 6 
3 1 5 9

上图中,2、4、7、8是拓扑排序的第一层、3、6是拓扑排序的第二层,1、5、9是拓扑排序的第三层,因此一共只需要3个级别。

此方法验证成立。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 1005;

int g[N][N]; //邻接矩阵,便于处理重边的情况
int n, m, s, a[N], b[N]; //a[i]存储所有停靠点 b[i]=1表示在第i站停靠
int in[N];
int depth[N], ans = 1; 

//通过拓扑排序,计算每个节点所在的深度,最大深度即不同的级别数
void bfs()
{
    queue<int> q;
    for(int i = 1; i <= n; i++)
    {
        if(in[i] == 0)
        {
            q.push(i);
            depth[i] = 1; //初始节点的深度
        } 
    }
    while (q.size())
    {
        int u = q.front(); q.pop();
        for(int v = 1; v <= n; v++)
        {
            if(g[u][v] == 1)
            {            
                if(--in[v] == 0)
                {
                    q.push(v);
                    depth[v] = depth[u] + 1;
                    ans = max(ans, depth[v]);
                } 
            }
        }
    }
    
}

int main()
{
    cin >> n >> m;
    while(m--)
    {
        cin >> s;
        memset(a, 0, sizeof(a)); 
        memset(b, 0, sizeof(b)); 
        for(int i = 1; i <= s; i++)
        {
            cin >> a[i]; //所有停靠站
            b[a[i]] = 1; //停靠站和非停靠站
        }
        for(int i = a[1]; i <= a[s]; i++) //遍历起点到终点之间的站
        {
            if(b[i] == 0)//取未停靠站
            {
                for(int j = 1; j <= s; j++) //遍历每一个停靠站a[j]
                {                
                    if(g[i][a[j]] == 0) in[a[j]]++; //记录入度,去重边
                    g[i][a[j]] = 1; //所有未停靠站和所有停靠站之间建立边
                }
            }
        }
    }
    bfs();
    cout << ans;
    return 0;
}

 

posted @ 2024-04-07 08:48  五月江城  阅读(60)  评论(0编辑  收藏  举报