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\n");
        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;
}

 

posted @ 2017-08-16 21:59  zzd233  阅读(836)  评论(0编辑  收藏  举报