题目
题意: 给一段abcdefab…路径,保证相邻的两个点一定有直接边相连。问你可以最多删掉多少点,使得 给定路径也可以作为 要想经过删后的所有点的最短路径。
思路: abcde 假如dis(a,b)+dis(b,c)=dis(a,c)。d这个点一定要删掉。因为此时ac之间经过d也是最短的。假如dis(a,c)+dis(c,d)>dis(a,d). c这个点一定要删掉。。显而易见。
哦对刚开始N=100,第九个样例n=99,我一直t 9。很奇怪呜呜。
#include<bits/stdc++.h>
using namespace std;
const int N=100+5,M=1e6+6;
int ma[N][N],p[M],ans[M];
char s[N];
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",s+1);
for(int j=1;j<=n;++j) (s[j]=='1')?ma[i][j]=1:ma[i][j]=101;
ma[i][i]=0;
}
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(ma[i][j]>ma[i][k]+ma[k][j]) ma[i][j]=ma[i][k]+ma[k][j];
int m;scanf("%d",&m);
for(int i=1;i<=m;++i) scanf("%d",&p[i]);
int num=0;ans[++num]=p[1];
for(int pre=1,las;pre<m;pre=las){
las=pre+2;
while(las<=m&&ma[p[pre]][p[las]]==ma[p[pre]][p[las-1]]+ma[p[las-1]][p[las]]) ++las;
ans[++num]=p[--las];
}
printf("%d\n",num);
for(int i=1;i<=num;++i) printf("%d ",ans[i]);
}