HDU 4725(最短路+思维建图)

题意:T组输入。n,m,c代表n个点,m个关系,相邻两层移动距离为C。每个点都会存在某一层上。

  一个点可以移动c到相邻的层上任意一点(不能移动c到同一层的一点上)。

问:第一个点到第n个点的最短路

思路:把每层看做其他的新加的点,第一层可以看作第n+1个点。

 -------------------------------------------------------------------------

我刚开始写的时候。

错解:第一层的所有点和第n+1个点建了双向,且权值为零的路。这样是错的,因为如果这样建图,同一层的点互相达到的距离为0.

正解:由第n+1个点到第一层的所有点建个单向的路,再由第一层的各个点建个单向的路到第一层相邻的两个层(就是第零层和第二层,实际上没有第零层,举个例子而已,k层的两边是n+k+1和n+k-1)的路,如果这层不存在就不需要建路。

注意第1层和第n层要特殊判断一下。

最短路跑完后如果d[n]==inf,侧代表无路

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <vector>
//const int maxn = 1e5+5;
#define ll long long
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
#define inf 0x3f3f3f3f
#define MAX INT_MAX
#define FOR(i,a,b) for( int i = a;i <= b;++i)
#define bug cout<<"--------------"<<endl
using namespace std;
int n,c,m,tot;
int ver[550000],edge[550000],Next[550000],head[550000],d[550000],val[550000],vis[550000];
void add(int x,int y,int z)
{
    ver[++tot] = y,edge[tot] = z;
    Next[tot] = head[x],head[x] = tot;
}
void dijkstra()
{
    priority_queue<pair<int,int> >que;
    memset(d,inf,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[1] = 0;
    que.push(make_pair(0,1));
    while(que.size())
    {
        int x = que.top().second;que.pop();
        if(vis[x] == 1) continue;
        vis[x] = 1;
        for(int i= head[x];i;i=Next[i])
        {
            int y = ver[i],z = edge[i];
            if(d[y] > d[x] + z)
            {
                d[y] = d[x] + z;
                que.push(make_pair(-d[y],y));
            }
        }
    }
}
void clearr()
{
    tot = 0;
    memset(head,0,sizeof(head));
    memset(val,0,sizeof(val));
    memset(vis,0,sizeof(vis));
}
int main()
{

    //  ios::sync_with_stdio(false);
    int T,casee = 0;
    scanf("%d",&T);
    while(T--)
    {
        clearr();
        scanf("%d %d %d",&n,&m,&c);
        for(int i=1;i<=n;++i)
        {
            int ceng;
            scanf("%d",&ceng);
            vis[ceng] = 1;
            val[i] = ceng;
        }
        for(int i=1;i<=m;++i)
        {
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        for(int i=1;i<=n;++i)
        {
            if(val[i] == 1)
            {
                add(val[i]+n,i,0);
                if(vis[val[i]+1] == 1 )
                {
                    add(i,val[i]+n+1,c);
                }
            }
            else if(val[i] == n)
            {
                add(val[i]+n,i,0);
                if(vis[val[i]-1] == 1) 
                {
                    add(i,val[i]+n-1,c);
                }
            }
            else
            {
                add(val[i]+n,i,0);
                if(vis[val[i]+1] == 1 )
                {
                    add(i,val[i]+n+1,c);
                }
                if(vis[val[i]-1] == 1 )
                {
                    add(i,val[i]+n-1,c);
                }
            }
        }
        dijkstra();
        if(d[n] == inf)   printf("Case #%d: -1\n",++casee);
        else printf("Case #%d: %d\n",++casee,d[n]);
    }



}

 

posted @ 2019-08-18 15:46  阿斯水生产线  阅读(152)  评论(0编辑  收藏  举报