BZOJ1073 k短路(A*算法)

A*算法,也叫启发式搜索,就是设计一个预估函数,然后在搜索的过程中进行有序的搜索,我们设到目前状态的花费为f(x),到目标状态的估计花费为h(x),那么我们按照h(x)+f(x)排序即可,这道题里起点到目前的距离为f(x),目前到终点的最短路为g(x),然后进行暴力搜索即可。—— by VANE

#include<bits/stdc++.h>
using namespace std;
const int N=55;
const int M=10050;
const int inf=1e9;
int n,m,S,T,tot,cnt,k;
int h1[N],h2[N],dis[N];
bool in[N];
struct edge
{
    int nxt,to,w;
    edge(){}
    edge(int to,int nxt,int w):
    to(to),nxt(nxt),w(w){}
}e1[M],e2[M];
void add(int a,int b,int c)
{
    e1[++tot]=edge(b,h1[a],c);
    e2[tot]=edge(a,h2[b],c);
    h1[a]=h2[b]=tot;
}
struct data
{
    int u,g;
    vector<int> path;
    bool vis[N];
    bool operator<(data oth) const
    {
        return g+dis[u]>oth.g+dis[oth.u];
    }
}t;
bool cmp(data x,data y)
{
    if(x.g!=y.g) return x.g<y.g;
    int l=min(x.path.size(),y.path.size());
    for(int i=0;i<l;++i)
    if(x.path[i]!=y.path[i])
    return x.path[i]<y.path[i];
    return x.path.size()<y.path.size();
}
void spfa()
{
    queue<int> Q;
    memset(dis,127,sizeof dis);
    dis[T]=0;
    Q.push(T);
    while(!Q.empty())
    {
        int x=Q.front();
        Q.pop();in[x]=0;
        for(int i=h2[x];i;i=e2[i].nxt)
        {
            if(dis[x]+e2[i].w>=dis[e2[i].to]) continue;
            if(!in[e2[i].to])
            {
                Q.push(e2[i].to);
                in[e2[i].to]=1;
            }
            dis[e2[i].to]=dis[x]+e2[i].w;
        }
    }
}
void solve()
{
    priority_queue<data> Q;
    vector<data> ans;
    t.u=S;t.g=0;t.vis[S]=1;
    t.path.push_back(S);
    Q.push(t);
    while(!Q.empty())
    {
        data x=Q.top();
        Q.pop();
        if(x.u==T)
        {
            cnt++;
            if(cnt>k&&x.g>ans[k-1].g) break;
            ans.push_back(x);
        }
        for(int i=h1[x.u];i;i=e1[i].nxt)
        {
            if(x.vis[e1[i].to]) continue;
            data y=x;
            y.u=e1[i].to;y.g=x.g+e1[i].w;
            y.path.push_back(y.u);y.vis[y.u]=1;
            Q.push(y);
        }
    }
    if(ans.size()<k)
    {
        puts("No");
        return;
    }
    sort(ans.begin(),ans.end(),cmp);
    for(int i=0;i<ans[k-1].path.size();++i)
    printf("%d%c",ans[k-1].path[i],(i+1)==ans[k-1].path.size()?'\n':'-');
}
int main()
{
    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;i<=m;++i)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    spfa();
    solve();
}

 

posted @ 2018-01-25 19:32  大奕哥&VANE  阅读(253)  评论(0编辑  收藏  举报