题面
题解
两问分开考虑
对于第一问, 每条线路建一个点, 线路上的站点向该点连一条 1 的边, 该点向线路上的点连一条 0 的边
直接最短陆即可
对于第二问
假设代表某条线路的点 (i) 的 (dis) 为 (d)
那么他所连接的站点要么 (dis) 为 (d), 要么 (dis) 为 (d-1)
由于这条线路是一条直的, 只用取 (dis) 为 (d - 1) 的前缀和后缀的 (max) 即可
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <map>
const int N = 8e5 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
int m, n, dis[N], head[N], cnte, cnt, p[N], len[N], S, T, pre[N], nxt[N], f[N];
struct edge { int to, nxt, cost; } e[N << 1];
string s;
vector<int> vec[N];
deque<int> q;
map<string, int> mp;
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
inline void adde(int u, int v, int w) { e[++cnte] = (edge) { v, head[u], w }, head[u] = cnte; }
void bfs()
{
memset(dis, -1, sizeof(dis)), dis[S] = 0;
q.push_back(S);
while(!q.empty())
{
int u = q.front(); q.pop_front();
for(int v, i = head[u]; i; i = e[i].nxt)
{
v = e[i].to; if(dis[v] != -1) continue;
dis[v] = dis[u] + e[i].cost;
e[i].cost ? q.push_back(v) : q.push_front(v);
}
}
}
bool cmp(int x, int y) { return dis[x + n] < dis[y + n]; }
void calc()
{
for(int i = 1; i <= m; i++) p[i] = i;
sort(p + 1, p + m + 1, cmp);
int l = 0, r = 1, tmp = 0;
while(r <= m && dis[p[r] + n] <= 0) r++;
while(l <= m)
{
l = r, tmp++;
while(r <= m && dis[p[r] + n] <= tmp) r++;
for(int u, j = l; j < r; j++)
{
u = p[j];
for(int k = 0; k <= len[u] + 1; k++) pre[k] = nxt[k] = -INF;
for(int v, k = 1; k <= len[u]; k++)
if(dis[v = vec[u][k - 1]] == tmp - 1) pre[k] = nxt[k] = f[v];
for(int k = 1; k <= len[u]; k++) pre[k] = max(pre[k], pre[k - 1] + 1);
for(int k = len[u]; k; k--) nxt[k] = max(nxt[k], nxt[k + 1] + 1);
for(int v, k = 1; k <= len[u]; k++)
if(dis[v = vec[u][k - 1]] == tmp) f[v] = max(f[v], max(pre[k], nxt[k]));
}
}
}
int main()
{
m = read <int> (), n = read <int> ();
for(int i = 1; i <= n; i++)
cin>>s, mp[s] = ++cnt;
for(int x, i = 1; i <= m; i++)
{
len[i] = read <int> ();
for(int j = 1; j <= len[i]; j++)
{
cin>>s, x = mp[s], vec[i].push_back(x);
adde(x, i + n, 1), adde(i + n, x, 0);
}
}
cin>>s, S = mp[s], cin>>s, T = mp[s];
bfs(), calc();
printf("%d
%d
", dis[T], f[T]);
return 0;
}