AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

Codeforces contest/229/problem/B. Planets    原题链接    简单

作者: 作者的头像   啼莺修竹 ,  2023-05-24 00:45:52 ,  所有人可见 ,  阅读 134


4


3
codeforce每日一题链接
每日一题题解视频
题目链接
题目分数:1700

题目描述

输入$n(2<n≤1e5) m(0≤m≤1e5)$表示一个$n$点$m$边的无向图(节点编号从$1$开始)。然后输入$m$条边,每条边包含$3$个数$a,b, c(1<c≤1e4)$,表示有一条边权为$c$的无向边连接$a$和$b$.保证无自环、无重边。然后输入$n$行,每行第一个数$k$表示数组$t[i]$的长度,然后输入数组$t[i]$。数组$t[i]$是一个严格递增序列,$0≤t[i] [j]<1e9$。所有$k$之和$≤1e5$。
初始时间为$0$。你从$1$出发,要去$n$。如果你在点$i$,但是当前时间在数组$t[i]$中,那么你必须等待$1$秒。如果下一秒仍然在$t[i]$中,那么继续等待$1$秒。依此类推。输出到达$n$的最早时间。如果无法到达$n$,输出$-1$。

样例

输入样例1
4 6
1 2 2
1 3 3
1 4 8
2 3 4
2 4 5
3 4 3
0
1 3
2 3 4
0
输出样例1
7
输入样例2
3 1
1 2 3
0
1 3
0
输出样例2
-1

算法

(spfa) $O(m)$

这道题我们先预处理一下,对于每一个点,我们创建一个$map$,如果当前时间需要加$1$的话,可以从$map$中$o(1)$的找到,可以从后向前循环,假设当前点会加$1$到$t$,那么对于它的前一个点,如果前一个点的时间等于现在点的时间减$1$,那么前一个点的也会一直加$1$到$t$,否则为前一个的时间加$1$,并将$t$动态修改。
那么我们就可以选用一个最短路算法了,这里我用的是$spfa$($dijkstra$在下面),在修改时间时,要在$map$中查询一下当前时间能不能走。注意,对于终点$n$,我们是不需要看时间的限制的,因为我们不需要再往下走了。

C++ 代码

//  https://www.acwing.com/blog/content/34755/

#include<bits/stdc++.h>

#define endl '\n'
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define pd push_back

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<double, double> PDD;

const int N = 1e5+10, M = N * 2, INF = 1e18;

int n, m;
map<int, int> g[N];
vector<int> f[N];
int e[M], ne[M], w[M], h[N], idx;
LL dist[N];
bool st[N];

inline void add(int a, int b, int c)
{
    e[idx]=b, w[idx]=c, ne[idx]=h[a], h[a]=idx++;
}

inline int spfa()
{
    for(int i=1;i<=n;i++) dist[i] = INF;
    dist[1] = g[1][0];
    queue<int> q;
    q.push(1);
    while(q.size())
    {
        auto u = q.front();
        q.pop();

        st[u] = false;
        for(int i=h[u];~i;i=ne[i])
        {
            int j = e[i];
            int t = dist[u] + w[i];
            if(j!=n && g[j].count(t)) t = g[j][t];
            if(dist[j]>t){
                dist[j] = t;
                if(!st[j]){
                    st[j] = true;
                    q.push(j);
                }
            }
        }
    }

    return dist[n];
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    memset(h, -1, sizeof h);
    cin>>n>>m;
    while(m--)
    {
        int a, b, c;
        cin>>a>>b>>c;
        add(a, b, c), add(b, a, c);
    }

    for(int i=1;i<=n;i++){
        int k;
        cin>>k;
        if(!k) continue;
        for(int j=0;j<k;j++){
            int x;
            cin>>x;
            f[i].pd(x);
        }
        int t = f[i][k-1] + 1;
        for(int j=f[i].size()-1;j>=0;j--)
        {
            if(j!=f[i].size()-1 && f[i][j]!=f[i][j+1]-1) t = f[i][j] + 1;
            g[i][f[i][j]] = t;
        }
    }

    LL d = spfa();
    if(d>=INF/2) cout<<-1<<endl;
    else cout<<d<<endl;

    return 0;
}

算法

(dijkstra) $O(n*log(m))$

C++ 代码

//  https://www.acwing.com/blog/content/34755/

#include<bits/stdc++.h>

#define endl '\n'
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define pd push_back

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<double, double> PDD;

const int N = 1e5+10, M = N * 2, INF = 1e18;

int n, m;
map<int, int> g[N];
vector<int> f[N];
int e[M], ne[M], w[M], h[N], idx;
LL dist[N];
bool st[N];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    auto add = [](int a, int b, int c){
        e[idx]=b, ne[idx]=h[a], w[idx]=c, h[a]=idx++;
    };

    memset(h, -1, sizeof h);
    cin>>n>>m;
    while(m--)
    {
        int a, b, c;
        cin>>a>>b>>c;
        add(a, b, c), add(b, a, c);
    }

    for(int i=1;i<=n;i++){
        int k;
        cin>>k;
        if(!k) continue;
        for(int j=0;j<k;j++){
            int x;
            cin>>x;
            f[i].pd(x);
        }
        int t = f[i][k-1] + 1;
        for(int j=f[i].size()-1;j>=0;j--)
        {
            if(j!=f[i].size()-1 && f[i][j]!=f[i][j+1]-1) t = f[i][j] + 1;
            g[i][f[i][j]] = t;
        }
    }

    auto dijkstra = [](){
        for(int i=1;i<=n;i++) dist[i] = INF;
        priority_queue<PII, vector<PII>, greater<PII>> heap;
        dist[1] = g[1][0];
        heap.push({g[1][0], 1});
        while(heap.size())
        {
            auto p = heap.top();
            heap.pop();

            int u = p.se;
            if(st[u]) continue;
            st[u] = true;

            for(int i=h[u];~i;i=ne[i])
            {
                int j = e[i];
                int t = dist[u] + w[i];
                if(j!=n && g[j].count(t)) t = g[j][t];
                if(dist[j]>t){
                    dist[j] = t;
                    heap.push({dist[j], j});
                }
            }
        }
        return dist[n];
    };

    LL d = dijkstra();
    if(d>=INF/2) cout<<-1<<endl;
    else cout<<d<<endl;

    return 0;
}

0 评论

你确定删除吗?

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息