[题解] [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; 
}
posted @ 2020-02-24 21:13  ztlztl  阅读(155)  评论(0编辑  收藏  举报