看错题意了一直看不懂题解浪费了好多时间...


思路:
先去考虑特殊的地方:
100
子序列
最短路径
一个个剖析:
100:考虑Floyd
子序列:DP?不懂
最短路径:考虑Floyd
我们要求的是子序列的方案,所以不大可能是DP
注意看它求的是什么,是按照子序列这种顺序跑,一定经过的是p这个路径
p这个路径保证是图中一个路径
换言之,是要删掉一些点,这些点满足:
一定在子序列的最短路径上
所以我们要删掉的是在最短路上的点!
那么考虑Floyd的松弛过程,当cur<dis时该点在最短路径上,所以删
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mxn=1e6+10;
const int mxe=1e6+10;
int N,M;
int dis[110][110],p[mxn];
string s[110];
void solve(){
	cin>>N;
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++){
			if(i==j) dis[i][j]=0;
			else dis[i][j]=1e18;
		} 
	}
	for(int i=1;i<=N;i++) cin>>s[i],s[i]=" "+s[i];
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++){
			if(s[i][j]=='1') dis[i][j]=1;
		}
	}
	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]);
			}
		}
	}
	cin>>M;
	for(int i=1;i<=M;i++) cin>>p[i];
	vector<int> v;
	v.push_back(p[1]);
	int last=p[1],cur=0;
	for(int i=2;i<=M;i++){
		cur+=dis[p[i-1]][p[i]];
		if(cur>dis[last][p[i]]){
			last=p[i-1];
			v.push_back(last);
			cur=dis[last][p[i]];
		}
	}
	v.push_back(p[M]);
	cout<<v.size()<<'\n';
	for(int i=0;i<v.size();i++) cout<<v[i]<<" \n"[i==v.size()-1];
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int __=1;//cin>>__;
	while(__--)solve();return 0;
}


















