[题解] [JSOI2015] 地铁线路

题面

题解

两问分开考虑

对于第一问, 每条线路建一个点, 线路上的站点向该点连一条 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\n%d\n", dis[T], f[T]); 
    return 0; 
}

猜你喜欢

转载自www.cnblogs.com/ztlztl/p/12358840.html
今日推荐