嘘~ 正在从服务器偷取页面 . . .

CF1204C Anna, Svyatoslav and Maps 题解


CF1204C Anna, Svyatoslav and Maps 题解

题目链接:CF1204C Anna, Svyatoslav and Maps

题意

对于 $n(n \le 100)$ 个点有向无环图,给出一个由 $m(m \le 10^6)$ 个点组成的的路径 $p$(不保证是简单路径,但保证对于 $1 \le i < m,p_i$ 与 $p_{i+1}$ 之间有边),
要求从 $p$ 中选出一个最短的子序列 $v$(假设长度为 $k$ ),满足 $v_1=p_1,v_k=p_m$ ,并且 $p$ 是按顺序经过 $v$ 的最短路径之一。

输入格式:

The first line contains a single integer $n$ ( $2 \le n \le 100$ ) — the number of vertexes in a graph.

The next $n$ lines define the graph by an adjacency matrix: the $j$ -th character in the $i$ -st line is equal to $1$ if there is an arc from vertex $i$ to the vertex $j$ else it is equal to $0$ . It is guaranteed that the graph doesn’t contain loops.

The next line contains a single integer $m$ ( $2 \le m \le 10^6$ ) — the number of vertexes in the path.

The next line contains $m$ integers $p_1, p_2, \ldots, p_m$ ( $1 \le p_i \le n$ ) — the sequence of vertexes in the path. It is guaranteed that for any $1 \leq i < m$ there is an arc from $p_i$ to $p_{i+1}$ .

输出格式

In the first line output a single integer $k$ ( $2 \leq k \leq m$ ) — the length of the shortest good subsequence. In the second line output $k$ integers $v_1,\ldots,v_k$ ( $1 \leq v_i \leq n$ ) — the vertexes in the subsequence. If there are multiple shortest subsequences, print any. Any two consecutive numbers should be distinct.

题目的意思有点鬼畜,其实就是问你这个最短路径构成的路线中有多少个点是可以删掉的。

注意到如果 $d(i,j) > d(i,k) + d(k,j)$ ,则点 $k$ 就不能删除。

也就是说在 $i,j$ 最短路径上的非 $i,j$ 点可以删除。

注意到 $n$ 非常小,所以我们可以用 $\mathtt{Floyd}$ 预处理一下最短路,然后扫一遍就好了。

时间复杂度 $\mathcal{O}(n^3 + |p|)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(115))
#define M ((int)(1e6+14))

char s[N],vis[N];
int n,m,g[N][N],d[N][N],p[M];
vector<int> vec;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i=1; i<=n; i++)
    {
        cin >> (s+1);
        for(int j=1; j<=n; j++)
        {
            d[i][j] = g[i][j] = s[j] - '0';
            if(d[i][j] == 0) d[i][j] = INF;
            if(i == j) d[i][j] = 0; 
        }
    }
    cin >> m;
    for(int i=1; i<=m; i++) cin >> p[i];
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++) down(d[i][j], d[i][k] + d[k][j]);
    vec.push_back(p[1]);
    int lst = p[1], cur = 0;
    for(int i=2; i<=m; i++)
    {
        cur += d[p[i-1]][p[i]];
        if(d[lst][p[i]] < cur)
            { lst = p[i-1]; vec.push_back(lst); cur = d[lst][p[i]]; }
    }
    vec.push_back(p[m]); cout << vec.size() << '\n';
    for(int i=0; i<vec.size(); i++) cout << vec[i] << " \n"[i==vec.size()-1];
    return 0;
}

参考文献

[1] https://te5555.blog.luogu.org/solution-cf1204c


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录