zoukankan      html  css  js  c++  java
  • POJ 3635

    题目链接:http://poj.org/problem?id=3635

    题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]

    一些口胡:

    说实话,上次写类似的二维状态最短路Gym 101873C - Joyride - [最短路变形][优先队列优化Dijkstra],我没能把手写二叉堆优化Dijkstra的给写出来。

    这次费了点功夫,也算是给写出来了,需要注意的点还是有点多的。而且我终于深刻理解为啥不推荐手写二叉堆了,主要是代码量相比优先队列实在是有点大……

    而且耗时好像和优先队列优化Dijkstra没啥差别。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int INF=0x3f3f3f3f; const int maxn=1e3+10; const int maxm=1e4+10; const int maxc=100+10; int n,m,q; int p[maxn]; struct Edge{ int u,v,w; Edge(int _u=0,int _v=0,int _w=0){u=_u,v=_v,w=_w;} }; vector<Edge> E; vector<int> G[maxn]; void init(int l,int r) { E.clear(); for(int i=l;i<=r;i++) G[i].clear(); } void addedge(int u,int v,int w) { E.push_back(Edge(u,v,w)); G[u].push_back(E.size()-1); } int d[maxn][maxc],vis[maxn][maxc]; struct Hnode{ int v,r; Hnode(){} Hnode(int _v,int _r) { v=_v, r=_r; } }; struct Heap { int sz; Hnode hp[4*maxn*maxc]; int pos[maxn][maxc]; void up(int now) { while(now>1) { int par=now>>1; if(d[hp[now].v][hp[now].r]<d[hp[par].v][hp[par].r]) //子节点小于父节点,不满足小顶堆性质 { swap(hp[par],hp[now]); swap(pos[hp[par].v][hp[par].r],pos[hp[now].v][hp[now].r]); now=par; } else break; } } void push(Hnode x) //插入权值为x的节点 { hp[++sz]=x; pos[x.v][x.r]=sz; up(sz); } Hnode top(){return hp[1];} void down(int now) { while((now<<1)<=sz) { int nxt=now<<1; if(nxt+1<=sz && d[hp[nxt+1].v][hp[nxt+1].r]<d[hp[nxt].v][hp[nxt].r]) nxt++; //取左右子节点中较小的 if(d[hp[nxt].v][hp[nxt].r]<d[hp[now].v][hp[now].r]) //子节点小于父节点,不满足小顶堆性质 { swap(hp[now],hp[nxt]); swap(pos[hp[now].v][hp[now].r],pos[hp[nxt].v][hp[nxt].r]); now=nxt; } else break; } } void pop() //移除堆顶 { hp[1]=hp[sz--]; pos[hp[1].v][hp[1].r]=1; down(1); } inline void clr() { sz=0; memset(pos,0,sizeof(pos)); } }H; int dijkstra(int c,int s,int t) { memset(d,0x3f,sizeof(d)); memset(vis,0,sizeof(vis)); H.clr(); d[s][0]=0, H.push((Hnode){s,0}); while(H.sz) { int u=H.top().v, r=H.top().r; H.pop(); if(u==t) return d[u][r]; if(vis[u][r]) continue; else vis[u][r]=1; if(r<c) { d[u][r+1]=d[u][r]+p[u], H.push((Hnode){u,r+1}); } for(int i=0;i<G[u].size();i++) { Edge &e=E[G[u][i]]; int v=e.v; if(r<e.w || vis[v][r-e.w]) continue; if(d[v][r-e.w]>d[u][r]) { d[v][r-e.w]=d[u][r]; if(H.pos[v][r-e.w]) H.up(H.pos[v][r-e.w]); else H.push((Hnode){v,r-e.w}); } } } return INF; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&p[i]); init(1,n); for(int i=1,u,v,w;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } scanf("%d",&q); for(int i=1,c,s,t;i<=q;i++) { scanf("%d%d%d",&c,&s,&t); int ans=dijkstra(c,s,t); if(ans<INF) printf("%d ",ans); else printf("impossible "); } }

    在百练上面可以使用pb_ds库,所以用在OpenJ_Bailian 3761 - Full Tank?上交了一发配对堆优化的Dijkstra。

    如果想自己写结构体类型放进配对堆的话,还要再写一个专门用来比较结构体的类型,里面要重定义"()"操作符。

    AC代码:

    #include<bits/stdc++.h>
    #include<ext/pb_ds/priority_queue.hpp>
    using namespace std;
    using namespace __gnu_pbds;
    const int INF=0x3f3f3f3f;
    const int maxn=1e3+10;
    const int maxm=1e4+10;
    const int maxc=100+10;
    
    int n,m,q;
    int p[maxn];
    
    struct Edge{
        int u,v,w;
        Edge(int _u=0,int _v=0,int _w=0){u=_u,v=_v,w=_w;}
    };
    vector<Edge> E;
    vector<int> G[maxn];
    void init(int l,int r)
    {
        E.clear();
        for(int i=l;i<=r;i++) G[i].clear();
    }
    void addedge(int u,int v,int w)
    {
        E.push_back(Edge(u,v,w));
        G[u].push_back(E.size()-1);
    }
    
    struct Qnode{
        int v;
        int d,r;
        Qnode(){}
        Qnode(int _v,int _d,int _r) {
            v=_v, d=_d, r=_r;
        }
    };
    struct Cmp{
        bool operator()(const Qnode& a,const Qnode& b)const {
            return a.d>b.d;
        }
    };
    typedef __gnu_pbds::priority_queue<Qnode,Cmp,pairing_heap_tag> Heap;
    int d[maxn][maxc];
    int dijkstra(int c,int s,int t)
    {
        memset(d,0x3f,sizeof(d));
    
        Heap Q;
        Heap::point_iterator id[maxn][maxc];
    
        d[s][0]=0;
        id[s][0]=Q.push(Qnode(s,d[s][0],0));
        while(!Q.empty())
        {
            int u=Q.top().v, r=Q.top().r; Q.pop();
            if(u==t) return d[u][r];
            if(r<c)
            {
                d[u][r+1]=d[u][r]+p[u];
                id[u][r+1]=Q.push(Qnode(u,d[u][r+1],r+1));
            }
            for(int i=0;i<G[u].size();i++)
            {
                Edge &e=E[G[u][i]]; int v=e.v;
                if(r<e.w) continue;
                if(d[v][r-e.w]>d[u][r])
                {
                    d[v][r-e.w]=d[u][r];
                    if(id[v][r-e.w]!=0) Q.modify(id[v][r-e.w],Qnode(v,d[v][r-e.w],r-e.w));
                    else id[v][r-e.w]=Q.push(Qnode(v,d[v][r-e.w],r-e.w));
                }
            }
        }
        return INF;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%d",&p[i]);
        init(1,n);
        for(int i=1,u,v,w;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        scanf("%d",&q);
        for(int i=1,c,s,t;i<=q;i++)
        {
            scanf("%d%d%d",&c,&s,&t);
            int ans=dijkstra(c,s,t);
            if(ans<INF) printf("%d
    ",ans);
            else printf("impossible
    ");
        }
    }
  • 相关阅读:
    Python的扩展接口[1] -> 串口通信
    Python的扩展接口[0] -> VISA仪器控制
    Python的工具包[2] -> matplotlib图像绘制 -> matplotlib 库及使用总结
    Python的工具包[1] -> pandas数据预处理 -> pandas 库及使用总结
    Python的工具包[0] -> numpy科学计算 -> numpy 库及使用总结
    Python的Web编程[1] -> Web服务器[0] -> Web 服务器与 CGI / WSGI
    Python的Web编程[0] -> Web客户端[1] -> Web 页面解析
    Python的Web编程[0] -> Web客户端[0] -> 统一资源定位符 URL
    Python与正则表达式[0] -> re 模块的正则表达式匹配
    解决Wamp的 Error D:wamp or PHP path 错误
  • 原文地址:https://www.cnblogs.com/dilthey/p/9992279.html
Copyright © 2011-2022 走看看