Description
N个点用M条有向边连接,每条边标有一个小写字母。 对于一个长度为D的顶点序列,回答每对相邻顶点Si到Si+1的最短回文路径。
如果没有,输出-1。 如果有,输出最短长度以及这个字符串。
Input
第一行正整数N和M ( 2 ≤ N ≤ 400 , 1 ≤ M ≤ 60,000 )
接下来M行描述边的起点,终点,字母。接下来D表示询问序列长度 ( 2 ≤ D ≤ 100 ) 再接下来D个1到N的整数
Output
对于D-1对相邻点,按要求输出一行。如果没合法方案,输出-1。 如果有合法,输出最短长度
Sample Input
6 7
1 2 a
1 3 x
1 4 b
2 6 l
3 5 y
4 5 z
6 5 a
3
1 5 3
Sample Output
3
-1
题解
妙
普通的bfs
考虑f[i][j]表示从i点到j点的最短回文串
大力bfs就会TLE
我们加一个g[i][j][k]表示 从i~j,除了最后一条边外都是回文串且最后一条边的权值为K
发现f和g会互相转移
再大力bfs…
就可以了
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#define LL long long
#define mp(x,y) make_pair(x,y)
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
inline void print(int x){write(x);printf(" ");}
int mp[410][410][30];
struct edge{int x,y,c,next;}a[590005],b[590005];int len1,last1[410],len2,last2[410][30];
void ins1(int x,int y,int c){len1++;a[len1].x=x;a[len1].y=y;a[len1].c=c;a[len1].next=last1[x];last1[x]=len1;}
void ins2(int x,int y,int c){len2++;b[len2].x=x;b[len2].y=y;b[len2].next=last2[x][c];last2[x][c]=len2;}
int g[410][410][30],f[410][410];
int n,m;char ch[10];
struct node
{
int x,y,pa;
node(){}
node(int _x,int _y,int _pa){x=_x;y=_y;pa=_pa;}
}tmp;
queue<node> q;
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
n=read();m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();scanf("%s",ch+1);
mp[x][y][ch[1]-'a'+1]=1;
}
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=26;k++)if(mp[i][j][k])ins1(i,j,k),ins2(j,i,k);
memset(f,63,sizeof(f));memset(g,63,sizeof(g));
for(int i=1;i<=n;i++)f[i][i]=0,q.push(node(i,i,0));
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j)
for(int k=1;k<=26;k++)if(mp[i][j][k])f[i][j]=1,q.push(node(i,j,0));
while(!q.empty())
{
tmp=q.front();q.pop();
int x=tmp.x,y=tmp.y;
if(!tmp.pa)
{
for(int k=last1[y];k;k=a[k].next)
{
int i=a[k].y,cal=a[k].c;
if(g[x][i][cal]>f[x][y]+1)g[x][i][cal]=f[x][y]+1,q.push(node(x,i,cal));
}
}
else
{
for(int k=last2[x][tmp.pa];k;k=b[k].next)
{
int i=b[k].y;
if(f[i][y]>g[x][y][tmp.pa]+1)f[i][y]=g[x][y][tmp.pa]+1,q.push(node(i,y,0));
}
}
}
int D=read();
int la=read();D--;
while(D--)
{
int x=read();
if(f[la][x]>=1e9)puts("-1");
else printf("%d\n",f[la][x]);
la=x;
}
return 0;
}