原題連結: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;
}