【Luogu】P2901牛慢跑(K短路模板)

  题目链接

  K短路居然用A*……奇妙。

  先建反图从终点(1)跑一遍最短路,再A*,用堆存当前点到终点距离+从起点到当前点距离。

  每次取出终点都可以视为发现了一个新的最短路。

  

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<queue>
#define maxn 1020
#define maxm 10020
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct Node{
    int pnt,dis;
    bool operator <(const Node a)const{
        return dis<a.dis;
    }
    bool operator ==(const Node a)const{
        return dis==a.dis;
    }
    bool operator <=(const Node a)const{
        return dis<=a.dis;
    }
};

struct Heap{
    Node heap[maxn*100];
    int size;
    Heap(){size=0;}
    inline void push(Node x){
        heap[++size]=x;
        register int i=size,k;
        while(i>1){
            k=i>>1;
            if(heap[k]<=heap[i])    return;
            swap(heap[k],heap[i]);
            i=k;
        }
    }
    inline Node pop(){
        Node ans=heap[1];    heap[1]=heap[size--];
        register int i=1,k;
        while((i<<1)<=size){
            k=i<<1;
            if(k<size&&heap[k|1]<heap[k])    k|=1;
            if(heap[i]<=heap[k])    return ans;
            swap(heap[k],heap[i]);
            i=k;
        }
        return ans;
    }
}s;

int ans[maxn],cnt;
int dis[maxn];
bool vis[maxn];

struct Picture{
    struct Edge{
        int next,to,val;
    }edge[maxm*2];
    int head[maxn],num;
    Picture(){memset(vis,0,sizeof(vis));num=0;memset(head,0,sizeof(head));}
    inline void add(int from,int to,int val){
        edge[++num]=(Edge){head[from],to,val};
        head[from]=num;
    }
    void prepare(int Start){
        memset(dis,127/3,sizeof(dis));    dis[Start]=0;
        queue<int>q;    q.push(Start);
        while(!q.empty()){
            int from=q.front();q.pop();
            vis[from]=0;
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(dis[to]<=dis[from]+edge[i].val)    continue;
                dis[to]=dis[from]+edge[i].val;
                if(vis[to])    continue;
                vis[to]=1;    q.push(to);
            }
        }
        return;
    }
    void Astar(int Start,int tme){
        s.push((Node){Start,dis[Start]});
        while(s.size){
            Node from=s.pop();
            int x=from.pnt,dst=from.dis;
            if(x==1)    ans[++cnt]=dst;
            if(tme==cnt)    return;
            for(int i=head[x];i;i=edge[i].next){
                int to=edge[i].to;
                s.push((Node){to,dst-dis[x]+edge[i].val+dis[to]});
            }
        }
    }
}Pre,Sub;

int main(){
    memset(ans,-1,sizeof(ans));
    int n=read(),m=read(),e=read();
    for(int i=1;i<=m;++i){
        int x=read(),y=read(),z=read();
        if(x<y)    swap(x,y);
        Pre.add(x,y,z);
        Sub.add(y,x,z);
    }
    Sub.prepare(1);
    Pre.Astar(n,e);
    for(int i=1;i<=e;++i)    printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2018-01-29 21:22  Konoset  阅读(431)  评论(0编辑  收藏  举报