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;
}

浙公网安备 33010602011771号