https://atcoder.jp/contests/abc197/tasks/abc197_f
过了一车人的套路我不会。。。
把题目转化成二维平面的模型,dis[u][v]表示从1到u,从n到v,一直走相同字母的距离
然后我们枚举每个点u:{s,e}的所有边,得到u:{s,e}->v:{s.v,e.v}这样的边,且他们走是相同的字母,这样枚举最大是m^2的
然后bfs就可以了,然后枚举中间dis[i][i]*2和dis[i][j]*2+1,i,j,中间有边,答案取最小方案就可以了
注意答案不能直接取dis[1][n]->dis[n][1]
4 4
1 2 b
2 4 a
1 3 a
3 4 b
这样从(1,n)走到(n,1)是一个环,但不是回文串
#include<bits/stdc++.h>
using namespace std;
const int maxl=1010;
int n,m,ans;
int dis[maxl][maxl];
struct ed{int v,l;};
vector<ed> e[maxl];
struct node{int s,e;};
vector<node> g[maxl][maxl];
char s[10];
bool vis[maxl][maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);vis[u][v]=vis[v][u]=true;
scanf("%s",s);
e[u].push_back(ed{v,s[0]-'0'});
e[v].push_back(ed{u,s[0]-'0'});
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(ed e1:e[i])
for(ed e2:e[j])
if(e1.l==e2.l)
g[i][j].push_back(node{e1.v,e2.v});
}
inline void mainwork()
{
memset(dis,0x3f,sizeof(dis));
dis[1][n]=0;int inf=dis[0][0];
queue<node> q;q.push(node{1,n});
while(!q.empty())
{
node u=q.front();q.pop();
for(node v:g[u.s][u.e])
if(dis[v.s][v.e]==inf)
{
dis[v.s][v.e]=dis[u.s][u.e]+1;
q.push(node{v.s,v.e});
}
}
ans=inf;
for(int i=1;i<=n;i++)
{
ans=min(ans,dis[i][i]*2);
for(int j=1;j<=n;j++)
if(vis[i][j])
ans=min(ans,dis[i][j]*2+1);
}
}
inline void print()
{
if(ans==dis[0][0])
ans=-1;
printf("%d",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}