比赛 2025暑期集训第5场图论专场 评测结果 AAAEEEEEEEEEE
题目名称 Telephone 最终得分 23
用户昵称 会挽弯弓满月 运行时间 1.523 s
代码语言 C++ 内存使用 4.92 MiB
提交时间 2025-07-09 11:59:42
显示代码纯文本
#include <bits/stdc++.h> 
#define pb push_back
using namespace std;
const int N=5e4+10,K=60,MAX=1e9;
int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<48||c>57){
		if(c==45) f=-1;
		c=getchar();
	}
	while(c>=48&&c<=57){
		x=x*10+c-48;
		c=getchar();
	}
	return f*x;
}
int n,k;
int b[N];
char s[K];
int g[K][K];
vector<int> a[N];
queue<int> q;
int dis[K];
void bfs(){
	for(int i=2;i<=n;i++) dis[i]=MAX;
	q.push(k+1);
	int u,si1,si2,i,j;
	int eu,ev;
	bool vis;
	while(!q.empty()){
		u=q.front();q.pop();
		for(int v=1;v<=k+2;v++){
			if(!g[u][v]) continue;
			vis=0;si1=a[u].size();si2=a[v].size();
			i=0;j=0;
			while(i<si1&&j<si2){
				eu=a[u][i];ev=a[v][j];
				if(dis[eu]+abs(eu-ev)<dis[ev]){
					dis[ev]=dis[eu]+abs(eu-ev);
					vis=1;
				}
				if(i==si1-1||eu>ev) j++;
				else i++;
			}
			if(vis) q.push(v);
		}
	}
	return;
}
int ans;
int main(){
	freopen("telephone.in","r",stdin);
    freopen("telephone.out","w",stdout);
	n=read();k=read();
	for(int i=1;i<=n;i++){
		b[i]=read();
		if(i==1||i==n) continue;
		a[b[i]].pb(i);
	}
	a[k+1].pb(1);//初 
	a[k+2].pb(n);//末 
	for(int i=1;i<=k;i++){
		scanf("%s",s+1);
		for(int j=1;j<=k;j++){
			g[i][j]=s[j]-48;
		}
	}
	if(b[1]==b[n]&&g[b[1]][b[n]]==1){
		printf("%d",n-1);
		return 0;
	}
	for(int i=1;i<=k;i++){
		if(g[b[1]][i]) g[k+1][i]=1;
		if(g[i][b[n]]) g[i][k+2]=1;
	}
	b[1]=k+1;b[n]=k+2;
	bfs();
	if(dis[n]==MAX) ans=-1;
	else ans=dis[n];
	printf("%d",ans);
	return 0;
}