题意:
中文不解释。
题解:
考虑将那些限制的条件插进AC自动机里面,然后在AC自动机上dp一下最短路就行了。
考虑dp[i][j]表示当前在第i个点上,在AC自动机的第j个点上的最短路。
然后dp转移看代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 typedef pair<double,double>P; 5 const int AC_N=1000,tyn=50; 6 int n,m,s[50]; 7 P a[60]; 8 double dp[55][505],inf=1e18; 9 10 struct AC_automation{ 11 int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot; 12 void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));} 13 void init(){tot=-1,fail[0]=-1,nw();} 14 void insert(int *s,int x=0){ 15 for(int i=0,w;s[i];x=tr[x][w],i++) 16 if(!tr[x][w=s[i]])nw(),tr[x][w]=tot; 17 cnt[x]++; 18 } 19 void build(int head=1,int tail=0){ 20 for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i]; 21 while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++) 22 if(tr[x][i]) 23 { 24 fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i]; 25 cnt[tr[x][i]]+=cnt[tr[fail[x]][i]]; 26 } 27 else tr[x][i]=tr[fail[x]][i]; 28 } 29 double dis(P &a,P &b) 30 { 31 return sqrt((a.first-b.first)*(a.first-b.first) 32 +(a.second-b.second)*(a.second-b.second)); 33 } 34 void solve() 35 { 36 F(i,0,n)F(j,0,tot)dp[i][j]=inf; 37 dp[1][tr[0][1]]=0; 38 F(i,1,n-1)F(j,0,tot)if(dp[i][j]!=inf) 39 { 40 F(k,i+1,n) 41 { 42 int nxt=tr[j][k]; 43 if(cnt[nxt])continue; 44 dp[k][nxt]=min(dp[k][nxt],dp[i][j]+dis(a[i],a[k])); 45 } 46 } 47 double ans=inf; 48 F(j,0,tot)ans=min(ans,dp[n][j]); 49 if(ans==inf)puts("Can not be reached!"); 50 else printf("%.2f ",ans); 51 } 52 }AC; 53 54 int main() 55 { 56 while(scanf("%d%d",&n,&m),n+m) 57 { 58 F(i,1,n)scanf("%lf%lf",&a[i].first,&a[i].second); 59 AC.init(); 60 F(i,1,m) 61 { 62 memset(s,0,sizeof(s)); 63 int num,x; 64 scanf("%d",&num); 65 F(j,1,num)scanf("%d",s+j-1); 66 AC.insert(s); 67 } 68 AC.build(),AC.solve(); 69 } 70 return 0; 71 }