注意标记一个点后,fail树上的子节点都会被标记
跑spfa,dp也可以
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include <set>
#include <queue>
#define ll long long
#define ld long double
#define lson l,m,rt<<1
#define pi acos(-1)
#define rson m+1,r,rt<<1|1
#define fo(i,l,r) for(int i = l;i <= r;i++)
#define fd(i,l,r) for(int i = r;i >= l;i--)
#define mem(x) memset(x,0,sizeof(x))
#define eps 1e-8
using namespace std;
const int maxn = 50050;
const ll inf = 1e9;
const ll mod = 998244353;
ll read() {
ll x=0,f=1;
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;
}
struct Trie{
int nxt[maxn][55],fail[maxn],end[maxn];
int root,L;
int newnode(){
for(int i = 0;i < 55;i++)
nxt[L][i] = -1;
end[L++]=0;
return L-1;
}
void init(){
L = 0;
root = newnode();
}
void insert(char buf[],bool bj){
int len = strlen(buf);
int now = root;
for(int i = 0;i < len;i++){
if(nxt[now][buf[i]]==-1)
nxt[now][buf[i]] = newnode();
now = nxt[now][buf[i]];
}
if(bj)end[now]++;
}
void build(){
queue<int> Q;
fail[root] = root;
for(int i = 0;i < 55;i++) {
if (nxt[root][i] == -1) {
nxt[root][i] = root;
} else {
fail[nxt[root][i]] = root;
Q.push((nxt[root][i]));
}
}
while(!Q.empty()){
int now = Q.front();
Q.pop();
if(end[fail[now]]) end[now]=1;
for(int i = 0;i < 55;i++){
if(nxt[now][i]==-1) {
nxt[now][i] = nxt[fail[now]][i];
}else{
fail[nxt[now][i]] = nxt[fail[now]][i];
Q.push(nxt[now][i]);
}
}
}
}
}ac;
int n,m,k;
double xx[maxn],yy[maxn];
char s[25];
struct dat{
int u;
int v;
double dis;
}now,nxt;
vector<dat> g[1050][55];
double d[1050][55];
bool vis[1050][55];
double ans;
void spfa(){
queue<dat> q;
fo(i,0,ac.L-1){
fo(j,1,n){
vis[i][j]=false;
d[i][j]=-100.0;
}
}
now.u = ac.nxt[0][1];now.v=1;
q.push(now);
vis[now.u][1]=true;d[now.u][1]=0.0;
while(!q.empty()){
now = q.front();
q.pop();
for(dat t:g[now.u][now.v]){
if(d[t.u][t.v]<0||(d[now.u][now.v]+t.dis<d[t.u][t.v])){
d[t.u][t.v] = d[now.u][now.v]+t.dis;
if(!vis[t.u][t.v]){
vis[t.u][t.v]=true;
q.push(t);
}
}
}
if(now.v==n){
if(ans<0||d[now.u][now.v] <ans)ans=d[now.u][now.v];
}
vis[now.u][now.v]=false;
}
}
int main() {
while(true){
ac.init();
ans=-1.0;
n=read();m=read();
if(!n&&!m)break;
fo(i,1,n){
xx[i]=read();yy[i]=read();
}
fo(i,1,m){
k=read();
int t;
fo(j,1,k){
t=read();
s[j-1]=t;
}
s[k]='\0';
ac.insert(s,true);
}
ac.build();
int v;
fo(i,0,ac.L-1){
fo(j,1,n) g[i][j].clear();
fo(j,1,n){
v=ac.nxt[i][j];
if(ac.end[v])continue;
now.u = v;
now.v = j;
fo(k,1,n){
if(k>=j)continue;
now.dis = sqrt((xx[j]-xx[k])*(xx[j]-xx[k]) + (yy[j]-yy[k])*(yy[j]-yy[k]));
g[i][k].push_back(now);
}
}
}
spfa();
if(fabs(ans)<eps)ans=0;
if(ans<-eps)puts("Can not be reached!");
else printf("%.2f\n",ans);
}
return 0;
}