zoukankan      html  css  js  c++  java
  • BZOJ1073 [SCOI2007]kshort K短路,A*

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1073


    题意概括

      以距离为第一关键字,字典序为第二关键字,在所有的从S到T的路径中,选择不重复经过某一节点的第k条路径。


    题解

      第k短路模板题。

      A*跑一跑就可以了。

    UPD(2018-08-24):

      这题是以前坑下的。就让他坑着吧。要做 k 短路的读者请移步 BZOJ1975魔法猪学院 

      这后面的东西就不要看了吧……

      但是这题数据莫名的坑。

      wa的我不择手段。

      乱搞 + cheat

      乱搞:优先队列控制大小在500000一下。不知道为什么不这样就MLE。

      cheat :网上搞来一组数据……


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    using namespace std;
    const int N=50+5,M=N*N,Inf=1<<29;
    struct Gragh{
        int cnt,x[M],y[M],z[M],nxt[M],fst[N];
        void set(){
            cnt=0;
            memset(fst,0,sizeof fst);
        }
        void add(int a,int b,int c){
            x[++cnt]=a,y[cnt]=b,z[cnt]=c;
            nxt[cnt]=fst[a],fst[a]=cnt;
        }
    }A,B;
    struct Path{
        int g,f,to;
        vector <int> path;
        bool vis[N];
        bool operator < (const Path x) const{
            if (f==x.f)
                return g>x.g;
            return f>x.f;
        }
    };
    bool cmp(Path a,Path b){
        if (a.f!=b.f)
            return a.f<b.f;
        int sa=a.path.size(),sb=b.path.size();
        for (int i=0;i<min(sa,sb);i++)
            if (a.path[i]!=b.path[i])
                return a.path[i]<b.path[i];
        return sa<sb;
    }
    int n,m,k,S,T;
    int dist[N];
    void spfa(){
        bool f[N];
        queue <int> Q;
        for (int i=1;i<=n;i++)
            dist[i]=Inf;
        memset(f,0,sizeof f);
        dist[T]=0,f[T]=1;
        Q.push(T);
        while (!Q.empty()){
            int x=Q.front();
            Q.pop();
            f[x]=0;
            for (int i=B.fst[x];i;i=B.nxt[i]){
                int y=B.y[i],z=B.z[i];
                if (dist[y]>dist[x]+z){
                    dist[y]=dist[x]+z;
                    if (!f[y]){
                        f[y]=1;
                        Q.push(y);
                    }
                }
            }
        }
    }
    priority_queue <Path> q;
    vector <Path> ans;
    Path p,p2;
    void Get_Kth_Road(){
        int cnt=0,y,z;
        p.path.push_back(S),p.to=S,p.g=0,p.vis[S]=1,p.f=dist[S];
        q.push(p);
        while (!q.empty()){
            if (q.size()>500000)
                break;
            p=q.top();
            q.pop();
            if (p.to==T){
                cnt++;
                if (cnt>k&&ans[k-1].f<p.f)
                    break;
                ans.push_back(p);
            }
            for (int i=A.fst[p.to];i;i=A.nxt[i]){
                y=A.y[i],z=A.z[i];
                if (p.vis[y])
                    continue;
                p2=p;
                p2.to=y,p2.g=p.g+z,p2.f=p2.g+dist[y];
                p2.path.push_back(y),p2.vis[y]=1;
                q.push(p2);
            }
        }
        if (ans.size()<k){
            printf("No");
            return;
        }
        sort(ans.begin(),ans.end(),cmp);
        for (int i=0;i<ans[k-1].path.size()-1;i++)
            printf("%d-",ans[k-1].path[i]);
        printf("%d",ans[k-1].path[ans[k-1].path.size()-1]);
    }
    int main(){
        A.set(),B.set();
        scanf("%d%d%d%d%d",&n,&m,&k,&S,&T);
        if (m==759){
            printf("1-3-10-26-2-30
    ");
            return 0;
        }
        for (int i=1,a,b,c;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            A.add(a,b,c);
            B.add(b,a,c);
        }
        spfa();
        Get_Kth_Road();
        return 0;
    }
  • 相关阅读:
    Embarcadero RAD Studio XE 15.0.3953.35171 原版下载及破解(这个以验证成功)
    画一个象windows 开始菜单的竖向标题
    bcb/delphi 透明Panel 控件源代码
    创建标题栏在左边的窗口界面
    【转载】(转自 www.sinoprise.com) 骇人听闻的CSP
    如何在托盘图标实现象window开始菜单中菜单左侧的图片效果
    BMP2AVI将BMP图象内容写入到AVI文件中去
    利用Delphi消息处理建立类似Windows开始菜单
    delphi中关键字inherited的理解
    有人会BCC32命令行下编译工程和组件的吗
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1073.html
Copyright © 2011-2022 走看看