The Shortest Path in Nya Graph(图论,最短路,建图)

题意:有一个双向图,上面的点多了一个属性:层数。一个点除了能走到与它链接的点,还能走到相邻的层数上的任意一个点,这种操作也需要成本。让你求最短路。

难点:建图。
在普通最短路问题的基础上,就多了层数的限制。 那么设每个点a都有一个“中转点ax”,这个点到中转点的成本为0。而且这个点的中转点ax相邻的中转点ax+1、ax-1到a的成本是cb。以这个理论建图,就可以得到如下代码。

 for (int i=1;i<=n;i++)
        {//中转点+(n+1)是为了不和i冲突
            operation(n+Ceng[i],i,0);//只能建立单向图,如果建立双向图会导致同一层上的边权为0
            operation(i,n+Ceng[i]-1,cb);
            operation(i,n+Ceng[i]+1,cb);
        }

这里的Ceng储存的是第i个点的层数,operation函数是将点放入链式向前星。

然后要考虑的问题有n、m都是1E5的。所以我使用SPFA+链式向前星。好像也可以用优先队列优化的Dijsktra,但我tcl不会优先队列优化。哭唧唧。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=4E5+5;
const int INF=1<<30;
struct node
{
    int next,to,val;
}qwe[maxn<<1];
int d[maxn];
bool vis[maxn];
int head[maxn<<1];
int Ceng[maxn];
int cnt,n,m,cb;
void operation (int a,int b,int c)
{
    qwe[cnt].next=head[a];
    qwe[cnt].to=b;
    qwe[cnt].val=c;
    head[a]=cnt++;
}
void reset ()
{
    memset(head,-1, sizeof(head));
    cnt=1;
}
void SPFA(int start)
{
    int tmp;
    memset(vis,false, sizeof(false));
    for (int i=0;i<=maxn;i++)
        d[i]=INF;
    d[start]=0;
    queue<int>q;
    q.push(start);
    vis[start]=true;
    while (!q.empty())
    {
        tmp=q.front();
        q.pop();
        vis[tmp]=false;
        for (int i=head[tmp];~i;i=qwe[i].next)
        {

            if (d[qwe[i].to]>d[tmp]+qwe[i].val)
            {
                d[qwe[i].to]=d[tmp]+qwe[i].val;
                if (vis[qwe[i].to]== false)
                {
                    q.push(qwe[i].to);
                    vis[qwe[i].to]=true;
                }
            }
        }
    }
}
int main ()
{
    int a,b, c = 0;
    int t;
    scanf ("%d",&t);
    for (int turn=1;turn<=t;turn++)
    {
        reset();
        scanf ("%d%d%d",&n,&m,&cb);
        for (int i=1;i<=n;i++)
            scanf ("%d",&Ceng[i]);
        for (int i=1;i<=n;i++)
        {
            operation(n+Ceng[i]+1,i,0);
            operation(i,n+Ceng[i],cb);
            operation(i,n+Ceng[i]+2,cb);
        }
        for (int i=1;i<=m;i++)
        {
            scanf ("%d%d%d",&a,&b,&c);
            operation(a,b,c);
            operation(b,a,c);
        }
        SPFA(1);
        printf ("Case #%d: ",turn);
        if(d[n]!=INF) printf ("%d\n",d[n]);
        else printf ("-1\n");
    }
    return 0;
}

P.S我一开始没有想到建图,而是去增加寻找最短路的方式。理所当然的TLE。

发布了33 篇原创文章 · 获赞 16 · 访问量 932

猜你喜欢

转载自blog.csdn.net/weixin_43925900/article/details/96098588