zoukankan      html  css  js  c++  java
  • Solution 「CF 575G」Run for beer

    \(\mathcal{Description}\)

      Link.

      给定 \(n\) 个点 \(m\) 条边的无向图,边有边权,一个人初始速度为 \(1\),每走一条边速度 \(\div10\),求从 \(1\) 走到 \(n\) 的最小耗时。

      \(n,m\le10^5\)\(0\le\text{边权}\le9\)

    \(\mathcal{Solution}\)

      直观地,路径长度即为把经过的边权从低位到高位写成的十进制数。

      首先排除前导 \(0\)——把从终点出发,仅走边权为 \(0\) 的边可达的结点全部与终点缩点。此时的最短路需要保证路径条数最少的前提下保证字典序最小。BFS 分层,维护当前层外围最优的一堆结点,用它们向下层扩展直到到达起点。

    \(\mathcal{Code}\)

    #include <queue>
    #include <cstdio>
    #include <vector>
    
    const int MAXN = 2e5, MAXM = 2e5;
    int n, m, ecnt, head[MAXN + 5], d[MAXN + 5], suf[MAXN + 5];
    bool vis[MAXN + 5];
    std::vector<int> curp, nxtp;
    std::queue<int> que;
    
    struct Edge { int to, cst, nxt; } graph[MAXM * 2 + 5];
    
    inline void link ( const int s, const int t, const int c ) {
    	graph[++ ecnt] = { t, c, head[s] };
    	head[s] = ecnt;
    }
    
    inline void initReach () {
    	for ( int i = 1; i <= n; ++ i ) d[i] = -1;
    	d[1] = 0, que.push ( 1 );
    	for ( int u; ! que.empty (); ) {
    		u = que.front (), que.pop ();
    		for ( int i = head[u], v; i; i = graph[i].nxt ) {
    			if ( ! ~ d[v = graph[i].to] ) {
    				d[v] = d[u] + 1, que.push ( v );
    			}
    		}
    	}
    }
    
    inline int zeroReach () {
    	int mind = d[n];
    	curp.push_back ( n ), vis[n] = true;
    	for ( int cur = 0; cur ^ curp.size (); ++ cur ) {
    		int u = curp[cur];
    		for ( int i = head[u], v; i; i = graph[i].nxt ) {
    			if ( ! vis[v = graph[i].to] && ! graph[i].cst ) {
    				curp.push_back ( v ), vis[v] = true, suf[v] = u;
    				if ( mind > d[v] ) mind = d[v];
    			}
    		}
    	}
    	return mind;
    }
    
    int main () {
    	scanf ( "%d %d", &n, &m );
    	for ( int i = 1, u, v, w; i <= m; ++ i ) {
    		scanf ( "%d %d %d", &u, &v, &w ), ++ u, ++ v;
    		link ( u, v, w ), link ( v, u, w );
    	}
    	initReach ();
    	int dist = zeroReach ();
    	bool zero = true;
    	for ( int l = dist; l; -- l ) {
    		int dig = 10;
    		for ( int u: curp ) {
    			for ( int i = head[u], v; i; i = graph[i].nxt ) {
    				if ( d[v = graph[i].to] + 1 == l && graph[i].cst < dig ) {
    					dig = graph[i].cst;
    				}
    			}
    		}
    		if ( dig ) zero = false;
    		if ( l == 1 || ! zero ) putchar ( dig ^ '0' );
    		for ( int u: curp ) {
    			for ( int i = head[u], v; i; i = graph[i].nxt ) {
    				if ( d[v = graph[i].to] + 1 == l && graph[i].cst == dig && ! vis[v] ) {
    					vis[v] = true, nxtp.push_back ( v ), suf[v] = u;
    				}
    			}
    		}
    		curp = nxtp, nxtp.clear ();
    	}
    	if ( zero ) putchar ( '0' );
    	int ans = 1, u;
    	for ( u = 1; u ^ n; ++ ans, u = suf[u] );
    	printf ( "\n%d\n0", ans ), u = 1;
    	do printf ( " %d", ( u = suf[u] ) - 1 ); while ( u ^ n );
    	putchar ( '\n' );
    	return 0;
    }
    
  • 相关阅读:
    XSS
    XSS练习小游戏
    CTF中常见的编码
    BugkuCTF
    A、B、C、D和E类IP地址
    JDK和JRE的区别及配置
    SQL注入漏洞测试(HTTP头注入)
    MS17-010远程溢出漏洞(CVE-2017-0143)拿权限
    SQL注入——布尔型盲注注入攻击——手工注入篇——SQL手工注入漏洞测试(MySQL数据库)
    mysql增删改查
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13413279.html
Copyright © 2011-2022 走看看