hdu-4511(AC自动机+最短路)

题意:让你求从1走到n的最短路,但是有些路径是不能走的,且走到每次走只能走比当前点大的点

解题思路:看到有些路径是不能走的,想到用AC自动机标记结点,跑出一个trie图来,在trie图上进行路径更新,dist【i】【j】表示在trie状态结点j的时候,到正常结点i的花费

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const double inf=1e18;
double dist[600][600];
int trie[6000][60];
int fail[600],tot;
int t[10];
double x[150],y[150];
bool visit[600];
int n,m,k;
void build_trie(int *arr,int len)
{
    int root=0;
    for(int i=1;i<=k;i++)
    {
        int id=arr[i];
        if(!trie[root][id])
            trie[root][id]=++tot;
        root=trie[root][id];
    }
    visit[root]=1;
}
void build_fail()
{
    queue<int>q;
    for(int i=1;i<=n;i++)
    {
        if(trie[0][i]!=0)
            q.push(trie[0][i]);
    }
    while(!q.empty())
    {
        int now=q.front();q.pop();
        if(visit[fail[now]]==1)
            visit[now]=1;
        for(int i=1;i<=n;i++)
        {
            if(!trie[now][i])
            {
                trie[now][i]=trie[fail[now]][i];
                continue;
            }
            fail[trie[now][i]]=trie[fail[now]][i];
            q.push(trie[now][i]);
        }
    }
}
void init()
{
    tot=0;
    memset(visit,0,sizeof(visit));
    memset(trie,0,sizeof(trie));
    memset(fail,0,sizeof( fail));
}
double dis(int a,int b)
{
    double tmp=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
    return tmp;
}
void solve()
{
    for(int i=1;i<=n;i++)
        for(int j=0;j<=tot;j++)
            dist[i][j]=inf;
    dist[1][trie[0][1]]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=tot;j++)
        {
            if(dist[i][j]<inf)
            {
                 for(int k = i + 1; k <= n; k++)
                        if(!visit[trie[j][k]])
                        {
                            dist[k][trie[j][k]] = min(dist[k][trie[j][k]],dist[i][j]+dis(i,k));
                        }
            }
        }
    }
    double ans=inf;
    for(int i=0;i<=tot;i++)
    {
        ans=min(ans,dist[n][i]);
    }
    if(ans>=inf)
        cout<<"Can not be reached!
";
    else
        printf("%.2f
",ans);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)return 0;
        init();
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&x[i],&y[i]);
        while(m--)
        {
            scanf("%d",&k);
            for(int i=1;i<=k;i++)
            {
                scanf("%d",&t[i]);
            }
            build_trie(t,k);
        }
        build_fail();
        solve();
    }
}
原文地址:https://www.cnblogs.com/huangdao/p/10805689.html