hdu4511小明系列故事——女友的考验(ac自动机+最短路)

时间:2021-08-30 09:06:39

链接

预处理出来任意两点的距离,然后可以顺着trie树中的节点走,不能走到不合法的地方,另开一维表示走到了哪里,依次来更新。

注意判断一下起点是不是合法。

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 510
#define LL long long
const double eps = 1e-;
const double pi = acos(-1.0);
const double INF = 1e21;
const int child_num = ;
double w[][];
class AC
{
private:
int ch[N][child_num];
int fail[N];
int val[N];
int id[];
int Q[N];
double dis[][N];
int sz;
public:
void init()
{
fail[] = ;
for(int i = ; i< child_num ; i++)
id[i] = i;
}
void reset()
{
memset(ch[],,sizeof(ch[]));
memset(val,,sizeof(val));
sz = ;
}
void insert(int *a,int k,int key)
{
int i,p=;
for(i = ;i <= k; i++)
{
int d = a[i];
if(ch[p][d]==)
{
memset(ch[sz],,sizeof(ch[sz]));
ch[p][d]= sz++;
}
p = ch[p][d];
}
val[p] = key;
}
void construct()
{
int i,head= ,tail = ;
for(i = ;i < child_num ; i++)
{
if(ch[][i])
{
fail[ch[][i]] = ;
Q[tail++] = ch[][i];
}
}
while(head!=tail)
{
int u = Q[head++];
val[u]|=val[fail[u]];
for(i = ; i < child_num ; i++)
{
if(ch[u][i])
{
fail[ch[u][i]] = ch[fail[u]][i];
Q[tail++] = ch[u][i];
}
else ch[u][i] = ch[fail[u]][i];
}
}
}
void work(int n)
{
int i,j,g;
for(i = ; i <= n ;i++)
for(j = ; j <= sz ;j++)
dis[i][j] = INF;
if(val[])
{
puts("Can not be reached!");
return ;
}
dis[][ch[][]] = ;
for(i = ; i <= n ;i++)
{
for(j = ; j < sz ;j++)
{
for(g = ; g <= n ;g++)
{
int np = ch[j][g];
if(val[np]) continue;
dis[g][np] = min(dis[g][np],dis[i][j]+w[i][g]);
}
}
}
double ans = INF;
for(i = ; i < sz ; i++)
{
ans = min(ans,dis[n][i]);
}
if(fabs(ans-INF)<eps) puts("Can not be reached!");
else
printf("%.2f\n",ans);
}
}ac;
struct node
{
double x,y;
}pp[];
double cdis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int a[];
int main()
{
int n,m,k,i,j;
ac.init();
while(scanf("%d%d",&n,&m)&&n&&m)
{
ac.reset();
for(i = ;i <= n; i++)
{
scanf("%lf%lf",&pp[i].x,&pp[i].y);
}
for(i = ; i <= n ;i++)
for(j = ; j <= n ;j++)
w[i][j] = cdis(pp[i],pp[j]);
for(i = ; i <= m ; i++)
{
scanf("%d",&k);
for(j= ;j <= k; j++)
scanf("%d",&a[j]);
ac.insert(a,k,);
}
ac.construct();
ac.work(n);
}
return ;
}