zoukankan      html  css  js  c++  java
  • [题解] [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
    %d
    ", dis[T], f[T]); 
    	return 0; 
    }
    
  • 相关阅读:
    代码对比软件——code compare
    IAR调试和keil调试的一点小区别
    谷访问歌助手
    X86架构的寄存器
    ant-design-pro
    js 闭包 作用域
    《三体》总结
    如何通过SQL注入盗取数据库信息
    《看见》总结
    《欲望的演化》总结
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12358840.html
Copyright © 2011-2022 走看看