HDU 4725 The Shortest Path in Nya Graph(优先队列+dijkstra)

题意:n个点、m条边、层与层之间的花费为c,给出每个点所在层(同一层的点联通花费为0),m条边每条边的花费,求1到n的最小花费;

思路:第一反应就是优先队列的dijkstra,层与层之间建边,点与点之间建边,层与包含点之间建边,点与相邻层之间建边;练习一下优先队列dijkstra和邻接表;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
int pp[500010],vv[500010],dist[500010];
int vis[500010],cnt,n,m,c;
int lay[500010];
struct Node
{
    int u,v,w;
    int next;
}edge[500010];//邻接表
struct node
{
    int pos,dd;
    bool operator <(const node&xx)const
    {
        return dd>xx.dd;
    }
}cur,now;
void addedge(int u,int v,int w)//邻接表
{
    cnt++;
    edge[cnt].v=v;
    edge[cnt].w=w;
    edge[cnt].next=pp[u];
    pp[u]=cnt;
}
priority_queue<node> q;
void dijkstra()
{
    int i,j,k,u,v,w;
    memset(vis,0,sizeof(vis));
    while(!q.empty()) q.pop();
    dist[1]=0;
    cur.pos=1;cur.dd=0;
    q.push(cur);
    while(!q.empty())
    {
        now=q.top();
        q.pop();
        u=now.pos;
        if(vis[u]) continue;
        vis[u]=1;
        for(i=pp[u];i;i=edge[i].next)
        {
            v=edge[i].v;
            w=edge[i].w;
            if(!vis[v]&&dist[v]>dist[u]+w)
            {
                dist[v]=dist[u]+w;
                cur.pos=v;cur.dd=dist[v];
                q.push(cur);
            }
        }
    }
}
int main()
{
    int i,j,k,u,v,w,t,temp;
    scanf("%d",&t);
    for(k=1;k<=t;k++)
    {
        scanf("%d%d%d",&n,&m,&c);
        memset(pp,0,sizeof(pp));
        memset(vv,0,sizeof(vv));
        memset(dist,INF,sizeof(dist));
        cnt=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&u);
            lay[i]=u;
            vv[u]=1;
        }
        for(i=1;i<n;i++)
        {
            if(vv[i]&&vv[i+1])//相邻层之间建边
            {
                addedge(n+i,n+i+1,c);//使用n个点以外的编号
                addedge(n+i+1,n+i,c);
            }
        }
        for(i=1;i<=n;i++)
        {
            addedge(lay[i]+n,i,0);//层与所包含点建边
            if(lay[i]>1) addedge(i,lay[i]+n-1,c);//点与相邻层建边
            if(lay[i]<n) addedge(i,lay[i]+n+1,c);//点与相邻层建边
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);//点与点之间建边
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dijkstra();
        temp=dist[n];
        printf("Case #%d: ",k);
        if(temp==INF) printf("-1\n");
        else printf("%d\n",temp);
    }
    return 0;
}

  

posted on 2015-04-23 20:14  大树置林  阅读(152)  评论(0编辑  收藏  举报

导航