Codeforces 1321D Navigation System

题目链接

题意:给你一张图和一条路径,沿着这条路径走,若走到某个点,该点不是之前的点算的最短路径上的一个点,就需要重新计算,求重新计算的最大次数与最小次数

已知终点,那我们可以反向跑一个最短路,求出每个点到终点\(t\)的距离\(d_u\), 假设现在是\(u\)
1.若\(u\)全部的可达点v满足 \(d_u > d_v + 1\), 则该点必须重新计算
2.若\(u\)的可达点至少有一点v满足 \(d_u = d_v + 1\), 且该点\(v\)不是题目给定的\(u\)点的下一点路径, 则最大次数+1

#include<bits/stdc++.h>
using namespace std;
#define ms(x,y) memset(x, y, sizeof(x))
#define lowbit(x) ((x)&(-x))
typedef long long LL;
typedef pair<int,int> pii;

const int maxn = 2e5+5;

int x[maxn], y[maxn], dis[maxn];
vector<int> G[maxn];
bool vis[maxn];

void dijkstra(int s) {
    ms(dis, 63), dis[s] = 0;
    priority_queue<pii> q;
    q.push(make_pair(0, s));
    while(!q.empty()) {
        auto u = q.top().second; q.pop();
        if(vis[u]) continue;
        vis[u] = true;
        for(auto v: G[u]) {
            if(dis[v] > dis[u] + 1) {
                dis[v] = dis[u] + 1;
                q.push(make_pair(-dis[v], v));
            }
        }
    }
}

void run_case() {
    int n, m;
    cin >> n >> m;
    for(int i = 0; i < m; ++i) {
        int tx, ty;
        cin >> tx >> ty;
        x[i] = tx, y[i] = ty;
        G[ty].push_back(tx);
    }
    int k; cin >> k;
    vector<int> path(k);
    for(auto &x: path) cin >> x;
    dijkstra(path[k-1]);
    for(int i = 1; i <= n; ++i) G[i].clear();
    for(int i = 0; i < m; ++i) G[x[i]].push_back(y[i]);
    int ans1 = 0, ans2 = 0;
    for(int i = 0; i < k-1; ++i) {
        int flag = 0, cnt = 0;
        for(auto v: G[path[i]]) {
            if(dis[path[i]]-1 == dis[v]) {
                if(v == path[i+1]) flag = 1;
                cnt++;
            }
        }
        if(!flag) ans1++, ans2++;
        else if(cnt > 1) ans2++;
    }
    cout << ans1 << " " << ans2;
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cout.flags(ios::fixed);cout.precision(2);
    //int t; cin >> t;
    //while(t--)
    run_case();
    cout.flush();
    return 0;
}
posted @ 2020-03-08 17:00  GRedComeT  阅读(98)  评论(0编辑  收藏  举报