zoukankan      html  css  js  c++  java
  • hdu4725 The Shortest Path in Nya Graph

    这道题看了下很多人都是把每一层拆成两个点然后建图做的。

    我的思路很直接,也不用建图,直接在更新每个点时更新他相邻的边和相邻的层,当然前提是每个点只更新一次,每个层也只更新一次,这样才能确保时间复杂度。

    这里我用了两个邻接表,一个是邻接边,一个是邻接层,最后用优先队列优化下。

    下面是代码

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<vector>
    using namespace std;
    const int M=2*111111;
    int fir[M],u[M],v[M],w[M],nxt[M],e;//边的邻接
    int n,m,c;
    int lfir[M],lu[M],lnxt[M],le;//层的邻接
    int lay[M];//表示每个点所在的层
    int dis[M],vis[M];//dis表示与起点距离,vis标记边是否访问过
    int lvis[M];//表示层是否访问过
    struct cmp
    {
        bool operator()(int a,int  b)
        {
            return dis[a]>dis[b];
        }
    };
    
    priority_queue<int,vector<int>,cmp>Q;
    void linsert(int la,int num)//插入层
    {
        lu[le]=num;
        lnxt[le]=lfir[la];
        lfir[la]=le++;
    }
    void insert(int a,int b,int c)//插入边
    {
        u[e]=a;v[e]=b;w[e]=c;
        nxt[e]=fir[a];
        fir[a]=e++;
    }
    const int inf=2000000000;
    int bfs()
    {
        int i,j,k,tm;
        for(i=1;i<=n;i++)dis[i]=(i==1?0:inf);
        memset(vis,0,sizeof(vis));
        memset(lvis,0,sizeof(lvis));
        while(!Q.empty())Q.pop();
        Q.push(1);
        while(!Q.empty())
        {
            int p=Q.top();Q.pop();
            if(p==n)break;
            if(vis[p])continue;
            vis[p]=1;
            for(k=fir[p];k!=-1;k=nxt[k])if(dis[ v[k] ]>dis[p]+w[k]){//更新边
                dis[ v[k] ]=dis[p]+w[k];
                Q.push(v[k]);
            }
    
            if(lvis[lay[p]])continue;
            lvis[lay[p]]=1;
    
            tm=lay[p]-1;
            for(k=lfir[tm];k!=-1;k=lnxt[k])if(dis[ lu[k] ]>dis[p]+c){//更新上一层
                dis[ lu[k] ]=dis[p]+c;
                Q.push(lu[k]);
            }
    
            tm=lay[p]+1;
             for(k=lfir[tm];k!=-1;k=lnxt[k])if(dis[ lu[k] ]>dis[p]+c){//更新下一层
                dis[ lu[k] ]=dis[p]+c;
                Q.push(lu[k]);
            }
        }
        if(dis[n]==inf)return -1;
        return dis[n];
    }
    int main()
    {
        int t,i,j,k,cas=1;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&c);
            le=0;
            memset(lfir,-1,sizeof(lfir));
            for(i=1;i<=n;i++){
                scanf("%d",&lay[i]);
                linsert(lay[i],i);
            }
            int a,b,c;
            e=0;
            memset(fir,-1,sizeof(fir));
            for(i=1;i<=m;i++){
                scanf("%d%d%d",&a,&b,&c);
                insert(a,b,c);
                insert(b,a,c);
            }
            int ans=bfs();
            printf("Case #%d: %d
    ",cas++,ans);
        }
        return 0;
    }
    


  • 相关阅读:
    WPF Popup弹出框箭头自动定位效果
    redis使用3
    linux常用命令
    Redis基础命令使用
    Redis使用笔记1
    jeesite常用注解记录
    Spring@Autowired注解与自动装配
    jeesite中的配置
    jeesite在eclipse中部署
    activiti流程连线与网关以及个人任务、组任务的指定方式
  • 原文地址:https://www.cnblogs.com/riskyer/p/3320132.html
Copyright © 2011-2022 走看看