看到n的范围, 想到跑一遍Floyd, 问题是如何求v. 答案是p的子序列, 所以肯定要在p上遍历一遍, 通过规范p的所有点都要遍历到, 就有
m
a
t
[
r
e
s
.
b
a
c
k
(
)
]
[
q
[
i
]
]
<
m
a
t
[
r
e
s
.
b
a
c
k
(
)
]
[
q
[
i
−
1
]
]
+
m
a
t
[
q
[
i
−
1
]
]
[
q
[
i
]
]
mat[res.back()][q[i]] < mat[res.back()][q[i - 1]] + mat[q[i - 1]][q[i]]
mat[res.back()][q[i]]<mat[res.back()][q[i−1]]+mat[q[i−1]][q[i]]即遍历p从点
r
e
s
.
b
a
c
k
(
)
到
p
[
i
]
不
经
过
p
[
i
−
1
]
会
更
短
res.back() 到 p[i]不经过p[i-1]会更短
res.back()到p[i]不经过p[i−1]会更短而题干有说一定要经过点p上的每一个点, 所以
p
[
i
−
1
]
p[i-1]
p[i−1]肯定要进入答案序列
#include<bits/stdc++.h>#include<bits/extc++.h>usingnamespace std;#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)#define _rev(i, a, b) for (int i = (a); i >= (b); --i)#define _for(i, a, b) for (int i = (a); i < (b); ++i)#define _rof(i, a, b) for (int i = (a); i > (b); --i)#define oo 0x3f3f3f3f#define ll long long#define db double#define eps 1e-8#define bin(x) cout << bitset<10>(x) << endl;#define what_is(x) cerr << #x << " is " << x << endl;#define met(a, b) memset(a, b, sizeof(a))#define all(x) x.begin(), x.end()#define pii pair<int, int>constint maxn =100+5;int n, m;//vector<vector<int> > mat(maxn, vector<int>(maxn, oo));int mat[maxn][maxn];intnxt(){int ret;char t;scanf(" %c",&t);return t -'0';}voidfloyed(){_rep(k,1, n){_rep(i,1, n){_rep(j,1, n){
mat[i][j]=min(mat[i][j], mat[i][k]+ mat[k][j]);}}}}signedmain(){
cin >> n;met(mat, oo);_rep(i,1, n){_rep(j,1, n){int tmp =nxt();if(i == j)mat[i][j]=0;if(tmp ==0)continue;
mat[i][j]= tmp;}}
cin >> m;
vector<int>q(m +1);_rep(i,1, m)
cin >> q[i];floyed();int dis = mat[q[1]][q[m]];
vector<int> res;
res.emplace_back(q[1]);int cur =0;_rep(i,2, m){if(mat[res.back()][q[i]]< mat[res.back()][q[i -1]]+ mat[q[i -1]][q[i]]){
res.emplace_back(q[i -1]);}}
res.emplace_back(q[m]);
cout << res.size()<< endl;for(auto i : res){
cout << i <<" ";}}