1204C Anna, Svyatoslav and Maps

题目大意

给你一个有向图和一个路径

让你在给定路径中选出尽量少的点使得新路径的最短路长度和原路径相等

给定路径相邻两点间距离为1

分析

先floyd求出两点间最短路

之后每次对于点i找到所有跟它的最短路距离=在序列上建个距离的点j

将dp[i]转移到dp[j]即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int d[110][110],g[110][110],n,m,dp[1001000],la[1001000],a[1001000],cnt,ans[1001000];
char s[110];
int main(){
    int i,j,k;
    scanf("%d",&n);
    memset(d,0x3f,sizeof(d));
    for(i=1;i<=n;i++){
      scanf("%s",s+1);
      for(j=1;j<=n;j++)
        g[i][j]=s[j]-'0';
    }
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        if(g[i][j])d[i][j]=g[i][j];
    for(k=1;k<=n;k++)
      for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)if(i!=j)
          d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    scanf("%d",&m);
    for(i=1;i<=m;i++)scanf("%d",&a[i]);
    memset(dp,0x3f,sizeof(dp));
    dp[1]=1;
    for(i=1;i<=m;i++){
      j=i;
      while(j+1<=m&&d[a[i]][a[j+1]]==j-i+1){
          j++;
        if(dp[i]+1<dp[j]){
            dp[j]=dp[i]+1;
            la[j]=i;
        }
      }
    }
    printf("%d\n",dp[m]);
    int x=m;
    while(x){
      ans[++cnt]=a[x];
      x=la[x];
    }
    for(i=cnt;i>0;i--)printf("%d ",ans[i]);
    puts("");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/11415181.html