codeforces1204 C. Anna, Svyatoslav and Maps

题面

Time limit 2000 ms
Mem limit 262144 kB
The main characters have been omitted to be short.
You are given a directed unweighted graph without loops with vertexes and a path in it (that
path is not necessary simple) given by a sequence of vertexes; for each
there is an arc from to .
Define the sequence of vertexes as good, if is a subsequence of , ,
, and is one of the shortest paths passing through the vertexes , , in that order.
A sequence is a subsequence of a sequence if can be obtained from by deletion of several
(possibly, zero or all) elements. It is obvious that the sequence is good but your task is to find
the shortest good subsequence.
If there are multiple shortest good subsequences, output any of them.

题意

给定一个DAG
指定一条路线p
请你找出一条路线p的子列v,使得在路线v上经过的最短路线为p

模型转化

找出子列可以转化为删去p中的一些点,而这些点不影响最短路径
那么对于某一部分a->b->c,
如果这是a->c的最短路,那么可以删掉b

思路

模拟上述思路
先跑一遍最短路径
开个容器储存答案
如果从上一个未删去的点走到当前点的距离 大于 这两个点的最短距离
那么这两个点之间的那个点必然不能删去,加到答案中
同时迁移上一个未删去的点 距离也重置一下

代码

#include <iostream>
#include <cstdio>
#include <vector>
#define VI vector<int>
using namespace std;
#define rg register
inline int read(){
    rg int x = 0, f = 1;
    rg char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}
const int N = 101, MAXN = 1e6 + 1;
int n, m;
int dis[N][N];
int p[MAXN];
VI ans;
inline void floyd(){
    for (int k(1); k <= n; k++)
        for (int i(1); i <= n; i++)
            for (int j(1); j <= n; j++)
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}

inline void init(){
    n = read();
    for (int i(1); i <= n; i++){
        for (int j(1); j <= n; j++){
            scanf("%1d", &dis[i][j]);
            if (!dis[i][j]) dis[i][j] = 1e9;
        }
        dis[i][i] = 0;
    }
    m = read();
    for (int i(1); i <= m; i++)
        p[i] = read();
}

inline void doit(){
    int prepos = p[1];
    ans.push_back(p[1]);
    int dist = 0;
    for (int i(2); i <= m; i++){
        dist += dis[p[i - 1]][p[i]];
        if (dis[prepos][p[i]] < dist){
            ans.push_back(p[i - 1]);
            prepos = p[i - 1];
            dist = dis[p[i - 1]][p[i]];
        }
    }
    ans.push_back(p[m]);
    printf("%d\n", ans.size());
    VI::iterator it = ans.begin();
    for (; it != ans.end(); it++)
        printf("%d ", *it);
}

int main(){
    init();
    floyd();
    doit();
    return 0;
}
posted @   ancer  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示