Problem - C - Codeforces
给你一个有n个顶点的无权图,以及由m个顶点的序列p1,p2,...,pm给出的路径(该路径不一定简单);对于每个1≤i<m,有一个弧从pi到pi+1。
如果v是p的子序列,v1=p1,vk=pm,并且p是按顺序通过v1,...,vk的最短路径之一,则定义k顶点的序列v1,v2,...,vk为好。
如果一个序列a可以通过删除几个(可能是零个或全部)元素从b中得到,那么这个序列a就是一个序列b的子序列。很明显,序列p是好的,但你的任务是找到最短的好子序列。
如果有多个最短的好子序列,请输出其中任何一个。
输入
第一行包含一个整数n(2≤n≤100)--图形中顶点的数量。
接下来的n行通过邻接矩阵定义图形:如果有一个从顶点i到顶点j的弧,第i行的第j个字符就等于1,否则就等于0。
下一行包含一个整数m(2≤m≤106)--路径中顶点的数量。
下一行包含m个整数p1,p2,...,pm(1≤pi≤n)--路径中顶点的序列。保证任何1≤i<m的情况下,都有一个弧从pi到pi+1。
输出
在第一行输出一个整数k (2≤k≤m) - 最短好子序列的长度。在第二行输出k个整数v1, ..., vk (1≤vi≤n) - 子序列中的顶点。如果有多个最短子序列,则打印任何一个。任何两个连续的数字都应该是不同的。
例子
输入
4
0110
0010
0001
1000
4
1 2 3 4
输出
3
1 2 4
输入
4
0110
0010
1001
1000
20
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
输出
11
1 2 4 2 4 2 4 2 4 2 4
输入
3
011
101
110
7
1 2 3 1 3 2 1
输出
7
1 2 3 1 3 2 1
输入
4
0110
0001
0001
1000
3
1 2 4
输出
2
1 4
题解:
(先入为主,觉得点数很大,不知道咋记录任意两点距离,好久没写floyd,忘了往这方面想了(点数很小))
首先存边(记得i == j可能是1,但是存边要把其看作0)坑点
跑floyd记录任意两点间最短距离,
起点存入答案数组,从i = 2开始,记录目前距离res为0
如果答案数组的top到b[i]的距离 < b[i-1] 到b[i]的距离,说明中间走的不是最短路,把b[i-1]存进去,res 更改为d[b[i-1]][b[i]],否则res += d[b[i-1]][b[i]],最后别忘了把b[m]也存到答案数组
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
char s[104][104];
int d[104][104];
int b[1000050];
int ans[1000050];
void solve()
{
int n;
cin >> n;
// memset(d,0x3f,sizeof d);
for(int i = 1;i <= n;i++)
{
cin >> s[i] + 1;
for(int j = 1;j <= n;j++)
{
if(s[i][j] == '1')
{
d[i][j] = 1;
}
else
{
d[i][j] = 1e9;
}
if(i == j)
d[i][j] = 0;
}
}
for(int k = 1;k <= n;k++)
{
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
{
d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
}
}
}
int m;
cin >> m;
for(int i = 1;i <= m;i++)
{
cin >> b[i];
}
int cnt = 0;
ans[++cnt] = b[1];
int res = 0;
for(int i = 2;i <= m;i++)
{
res += d[b[i - 1]][b[i]];
if(d[ans[cnt]][b[i]] < res)
{
ans[++cnt] = b[i - 1];
res = d[b[i - 1]][b[i]];
}
}
ans[++cnt] = b[m];
cout << cnt <<"\n";
for(int i = 1;i <= cnt;i++)
cout <<ans[i] << " ";
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}