CF1204(最短路+思维)

Anna, Svyatoslav and Maps - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

首先用floyd跑一遍最短路。

对于p序列的两个点:如果 dis[p[i]][p[j]] = j-i,则序列p是经过 p[i]~p[j]的最短路.

假设现在存入 v 数组的最后一个点是p[i],找到p[i]后第一个点,使得 dis[p[i]][p[j]] < j - i,此时把 p[j]存入v数组,就不满足题意的:p是按顺序经过v的最短路径之一。

显然p[i+1],p[i+2]~p[j-1]是符合v数组的条件的,但为了让 v 的长度最短,我们只用将 p[j-1] 存入v数组,这样同时满足 dis[p[i]][p[j-1]] = (j-1)-i,dis[p[j-1]][p[j]]=j-(j-1)。

最后再将p[n]存入v数组。

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back   
#define popb pop_back  
#define fi first
#define se second
const int N=150;
const int M=1e6+10;
const int inf=0x3f3f3f3f;     
//const ll INF=0x3ffffffffffff;
int T,n,m,dis[N][N],p[M];
char s[N][N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) dis[i][j]=inf;
    for(int i=1;i<=n;i++) dis[i][i]=0;
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    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]);
    m=read();
    for(int i=1;i<=m;i++) p[i]=read();
    vector<int> v;
    v.pb(1);
    for(int i=2;i<=m;i++)
        if(dis[p[v.back()]][p[i]]<i-v.back()) v.pb(i-1);
    v.pb(m);
    printf("%d\n",v.size());
    for(auto x:v) printf("%d ",p[x]);
    return 0;
}

 

posted @ 2023-03-05 18:11  QAQ啥也不会  阅读(9)  评论(0编辑  收藏  举报