zoukankan      html  css  js  c++  java
  • 「HDU5361」In Touch

    题目

    点这里看题目。

    分析

    首先注意到问题就是一个最短路的模型,但是边是连在区间上的,这提示我们应该使用数据结构优化建图

    考虑一个不那么粗暴的做法。一种想法是,由于用 Dijkstra 跑最短路的时候,只要出了堆就可以不用管了,那么我们可以每次只访问区间内有效的位置;这个位置可以使用链表/并查集维护。

    然而这个方法并没有用......Dijkstra 和 BFS 不同的地方在于,Dijkstra 中每个点虽然只会被出一次堆,但是会被访问多次,而 BFS 则只会被访问一次。此题还有一个性质,边权只和边的起点相关,如果我们在堆里维护好到达某个点的最短距离,等到这个最短距离被取出了之后,我们再去找可以到达的点,并且将这个最短距离赋给那些点,就可以保证每个点只访问一次。

    小结:

    1. 理清每个算法之间的差异,避免一些理解错误的问题;
    2. 注意,求最短路的时候,“计算距离”和“将距离对应到点”并非绑定在一起的,通过将这两个过程拆开我们可以处理这种特殊情况;

    代码

    #include <queue>
    #include <cstdio>
    #include <utility>
    #include <iostream>
    
    #define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )
    #define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )
    
    typedef long long LL;
    
    const LL INF = 1e18;
    const int MAXN = 2e5 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
        x = 0; char s = getchar(); int f = 1;
        while( ! ( '0' <= s && s <= '9' ) ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
        while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
        x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
        if( x < 0 ) putchar( '-' ), x = -x;
        if( 9 < x ) write( x / 10 );
        putchar( x % 10 + '0' );
    }
    
    typedef std :: pair<LL, int> Node;
    
    std :: priority_queue<Node, std :: vector<Node>, std :: greater<Node> > q;
    
    LL dist[MAXN];
    bool vis[MAXN];
    
    int fa[MAXN];
    int l[MAXN], r[MAXN], c[MAXN];
    int N;
    
    void MakeSet( const int n ) { rep( i, 1, n ) fa[i] = i; }
    int FindSet( const int u ) { return fa[u] = ( fa[u] == u ? u : FindSet( fa[u] ) ); }
    void UnionSet( const int u, const int v ) { fa[FindSet( u )] = FindSet( v ); }
    
    void Dijkstra( const int s )
    {
        MakeSet( N + 1 );
        while( ! q.empty() ) q.pop();
        rep( i, 1, N ) dist[i] = INF, vis[i] = false;
        q.push( std :: make_pair( dist[s] = c[s], s ) );
        while( ! q.empty() )
        {
            int u = q.top().second; q.pop(), vis[u] = true;
            int lef = std :: max( u - r[u], 1 ), rig = u - l[u];
            if( lef <= rig )
                for( int v = FindSet( lef ) ; v <= rig ; v = FindSet( v + 1 ) )
                {
                    if( dist[v] > dist[u] + c[v] ) 
                        q.push( std :: make_pair( dist[v] = dist[u] + c[v], v ) );
                    UnionSet( v, v + 1 );
                }
            lef = u + l[u], rig = std :: min( N, u + r[u] );
            if( lef <= rig )
                for( int v = FindSet( lef ) ; v <= rig ; v = FindSet( v + 1 ) )
                {
                    if( dist[v] > dist[u] + c[v] ) 
                        q.push( std :: make_pair( dist[v] = dist[u] + c[v] , v ) );
                    UnionSet( v, v + 1 );
                }
        }
    }
    
    int main()
    {
        int T;
        read( T );
        while( T -- )
        {
            read( N );
            rep( i, 1, N ) read( l[i] );
            rep( i, 1, N ) read( r[i] );
            rep( i, 1, N ) read( c[i] );
            Dijkstra( 1 );
            rep( i, 1, N ) 
            {
                if( vis[i] ) write( dist[i] - c[i] );
                else write( -1 ); putchar( i == N ? '
    ' : ' ' );
            }
        }
        return 0;
    }
    
  • 相关阅读:
    安装7-Zip后,鼠标右键菜单出现选项(CRC SHA)
    Windows添加右键菜单【转载】
    基于Visual Studio开发C++/Qt项目的使用笔记
    数组中的重复数字
    zookeeper的通知机制
    zookeeper有几种部署模式? zookeeper 怎么保证主从节点的状态同步?
    什么是springcloud?springcloud断路器的作用是什么?springcloud的核心组件有什么?
    springboot实现热部署的几种方式
    springboot的核心配置文件
    什么是springboot?为什么要用springboot?
  • 原文地址:https://www.cnblogs.com/crashed/p/15158381.html
Copyright © 2011-2022 走看看