大体思路就是 给你 n个点 m条边 每个边上有个字符C 询问 从点1 到 点 n 一条路径字符按顺序组成的回文最短路 首先可以想到 双向bfs 因为回文一定是 字符相同 此时我们只需要点1和点n 同时跑最短路就可以了 数据因为是 1000 所以25 * 1000 * 1000 够了
有两个判断是否为回文的 形态 一种是两条边走到了一个点 另一种是 两条边走到了两个点 但是相邻只有一个点 只需要特判就行
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N = 1e3 + 10;
int n,m;
vector<int>v[N][30];
int mp[N][N];
int dist[N][N];
struct node{
int x,y,sum;
bool operator < (const node &p)const{
return sum > p.sum;
}
};
int flag[N][N],ans = 0x3f3f3f3f;
void dij(){
memset(dist,0x3f,sizeof dist);
priority_queue<node>q;
q.push({1,n,0});
dist[1][n] = 0;
while(q.size()){
node p = q.top();
q.pop();
if(flag[p.x][p.y]) continue;
flag[p.x][p.y] = 1;
if(p.x == p.y){
ans = min(ans,dist[p.x][p.y]);
}
if(mp[p.x][p.y]) ans = min(ans,dist[p.x][p.y] + 1);
for(int i = 0; i <= 25; i++){
for(auto j : v[p.x][i]){
for(auto k : v[p.y][i]){
if(dist[j][k] > dist[p.x][p.y] + 2){
dist[j][k] = dist[p.x][p.y] + 2;
q.push({j,k,dist[j][k]});
}
}
}
}
}
}
int main(){
cin >> n >> m;
for(int i = 1; i <= m; i++){
int a,b;char c;
scanf("%d %d %c",&a,&b,&c);
v[a][c - 'a'].push_back(b);
v[b][c - 'a'].push_back(a);
mp[a][b] = 1;
mp[b][a] = 1;
}
dij();
if(ans == 0x3f3f3f3f) cout << -1 <<endl;
else cout << ans <<endl;
return 0;
}