codeforces1204 C. Anna, Svyatoslav and Maps (floyd)

Anna, Svyatoslav and Maps

You are given a directed unweighted graph without loops with n vertexes and a path in it (that path is not necessary simple) given by a sequence p1,p2,…,pm of m vertexes; for each 1≤i<m there is an arc from pi to pi+1.

Define the sequence v1,v2,…,vk of k vertexes as good, if v is a subsequence of p, v1=p1, vk=pm, and p is one of the shortest paths passing through the vertexes v1, …, vk in that order.

A sequence a is a subsequence of a sequence b if a can be obtained from b by deletion of several (possibly, zero or all) elements. It is obvious that the sequence p is good but your task is to find the shortest good subsequence.

If there are multiple shortest good subsequences, output any of them.

Input

The first line contains a single integer n (2≤n≤100) — the number of vertexes in a graph.

The next n lines define the graph by an adjacency matrix: the j-th character in the i-st line is equal to 1 if there is an arc from vertex i to the vertex j else it is equal to 0. It is guaranteed that the graph doesn’t contain loops.

The next line contains a single integer m (2≤m≤106) — the number of vertexes in the path.

The next line contains m integers p1,p2,…,pm (1≤pi≤n) — the sequence of vertexes in the path. It is guaranteed that for any 1≤i<m there is an arc from pi to pi+1.

Output

In the first line output a single integer k (2≤k≤m) — the length of the shortest good subsequence. In the second line output k integers v1, …, vk (1≤vi≤n) — the vertexes in the subsequence. If there are multiple shortest subsequences, print any. Any two consecutive numbers should be distinct.

Examples

input
4
0110
0010
0001
1000
4
1 2 3 4

output

3
1 2 4

input

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

output

11
1 2 4 2 4 2 4 2 4 2 4

input

3
011
101
110
7
1 2 3 1 3 2 1

output

7
1 2 3 1 3 2 1

input

4
0110
0001
0001
1000
3
1 2 4

output

2
1 4

分析:

先用floyd跑出各顶点间的最短路。
把p(1)加入答案,然后沿着题目给的路径序列遍历,
如果答案中的最后一个顶点到当前遍历到的顶点的最短距离
小于原序列中两点间的距离和,则答案加上p(i-1),并且继续遍历路径,
遍历完之后在最后加上p(m)

代码带注释

补充说明:
假设原序列为a,b,c,d
如果a->c的最短距离小于a->b+b->c,则b不能被删掉,因为删掉之后a->c的最短路径就不经过b了,
如果不能删,则答案序列最多只能到c的前面一个点也就是b,答案序列加上b,然后判断b->d
否则能删,如果能删就继续判断a->d

code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=105;
int g[maxm][maxm];
int p[maxm*maxm*maxm];
int ans[maxm*maxm*maxm],cnt;
int n,m;
void input(){
    scanf("%d",&n);
    getchar();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            char t=getchar();
            g[i][j]=(t=='1')?1:inf;
            if(i==j)g[i][j]=0;//记得加这个
        }
        getchar();
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&p[i]);
    }
}
void floyd(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
            }
        }
    }
}
void solve(){
    ans[++cnt]=p[1];
    int dis=0;//dis为当前点到答案最后一个点的距离
    for(int i=2;i<=m;i++){
        dis+=g[p[i-1]][p[i]];//累加
        if(dis>g[ans[cnt]][p[i]]){//如果超过了答案序列最后一个点到当前点的最短距离
            ans[++cnt]=p[i-1];//则把p[i-1]加入答案
            dis=g[ans[cnt]][p[i]];//更新dis
        }
    }
    ans[++cnt]=p[m];//记得加入p[m]
    printf("%d\n",cnt);
    for(int i=1;i<=cnt;i++){
        printf("%d ",ans[i]);
    }
}
int main(){
    input();
    floyd();
    solve();
    return 0;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值