【题目描述】题目

【题意】中文题目,题意就不解释了

【分析】用dis[u][x]表示到达u点,飞行符状态为x所需的最少时间。假设x=0表示飞行符未使用过,x=1表示已经使用过一次,x=2表示用过两次,很显然,x=0的状态,能转移到x=1(用一次)和x=0(不用),x=1的状态只能转移到x=2(再用一次或者不用了),x=2的状态只能转移到x=2(必须的)。最后从dis[1][0]状态开始,跑一次spfa,输出min(dis[n][0],dis[n][1],dis[n][2])即可。

【AC代码】

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stdlib.h>
#include<algorithm>
#define maxn 1100
#define LL long long
using namespace std;
#define inf 1e17
LL num,p[maxn],n;
struct node
{
    LL st,en,next,len;
}E[maxn*maxn];
void init()
{
    num=0;
    memset(p,-1,sizeof(p));
}
void add(LL st,LL en,LL len)
{
    E[num].st=st;
    E[num].en=en;
    E[num].len=len;
    E[num].next=p[st];
    p[st]=num++;
}
struct Node
{
    LL dis,id,flog;
};
LL dis[maxn][3];
bool vis[maxn][3];
void solve()
{
    for(LL i=1;i<=n;i++)
        for(LL j=0;j<3;j++)
        dis[i][j]=inf,vis[i][j]=0;
    queue<Node> q;
    Node st,en;
    st.dis=0,st.id=1,st.flog=2;
    q.push(st);
    vis[1][2]=1;
    dis[1][2]=0;
    while(q.size())
    {
        st=q.front();
        q.pop();
        for(LL i=p[st.id];i!=-1;i=E[i].next)
        {
            en.id=E[i].en;
            if(st.flog>=1)
            {
                en.dis=st.dis;
                en.flog=st.flog-1;
                if(dis[en.id][en.flog]>en.dis)
                {
                    vis[en.id][en.flog]=1;
                    dis[en.id][en.flog]=en.dis;
                    q.push(en);
                }
                en.dis=st.dis+E[i].len;
                if(st.flog==2) en.flog=2;
                else if(st.flog==1) en.flog=0;
                if(dis[en.id][en.flog]>en.dis)
                {
                    vis[en.id][en.flog]=1;
                    dis[en.id][en.flog]=en.dis;
                    q.push(en);
                }
            }
            else if(st.flog==0)
            {
                en.dis=st.dis+E[i].len;
                en.flog=0;
                if(dis[en.id][en.flog]>en.dis)
                {
                    vis[en.id][0]=1;
                    dis[en.id][en.flog]=en.dis;
                    q.push(en);
                }
            }
        }
    }
}
int main()
{
    while(scanf("%lld",&n)==1)
    {
        init();
        for(LL i=1;i<=n;i++)
            for(LL j=1;j<=n;j++)
        {
            LL x;
            scanf("%lld",&x);
            if(x==0) continue;
            add(i,j,x);
        }
        solve();
        LL ans=inf;
        for(LL i=0;i<3;i++)
            ans=min(ans,dis[n][i]);
        if(ans==inf) puts("-1");
        else printf("%lld\n",ans);
    }
    return 0;
}