[jzoj1163]第k短路

来源:互联网 发布:python ascii计算 编辑:程序博客网 时间:2024/06/03 13:46

Description

Bessie 来到一个小农场,有时她想回老家看看她的一位好友。她不想太早地回到老家,因为她喜欢途中的美丽风景。她决定选择K短路径,而不是最短路径。
农村有 R (1≤R≤100,000) 条单向的路,每条路连接 N (1≤N≤10000) 个结点中的两个。结点的编号是 1..N。Bessie 从结点 1出发,她的朋友(目的地)在结点 N。
同一个点可以多次经过。K短路的定义:假设从1出发,有M条长度不同的路径可以到达点N,则K短路就是这M条路径中第K小的路径长度。

Input

Line 1: 三个用空格分隔的整数 N,R,K((1≤n≤10000,1≤R≤100000,1≤K≤10000)
Lines 2..R+1: 每行包含三个用空格分隔的整数x,y,len(1≤x,y≤n,1≤len≤10000),表示x到y有一条长度为len的单向道路。

Output

输出包括一行,一个整数,第K短路的长度。

Sample Input

4 4 2
1 2 100
2 4 200
2 3 250
3 4 100

Sample Output

450

题解

首先,此题数据有问题,能拿80的话就说明算法对了,然后看看我的输入,改一下就过了。
然后就是关于第k短路的算法。
这一篇blog讲的比较好:
http://blog.csdn.net/z_mendez/article/details/47057461
然后说一下我的理解:
预处理出来每个点到终点的最短路,然后从起点开始A*,每次取f值最大的点,将它周围的点都更新值放到堆里,每一次搜到终点记一次数,当计数达到k次时就是答案了。
为什么这么做是对的呢?在我看来,这样就相当于在枚举起点和终点之间的点,因为是用堆存储的,所以效率较高,这也是一个搜索的过程,只不过它可以“判断”下一步走什么更容易到达下一条路。
然后还有就是看清题意,比如这个题,它对第k短路的定义就是所有长度不相等的路排序之后的第k个,所以我们要判重,这里判重用map就可以了。
代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#include<queue>#include<map>#define ll long longusing namespace std;inline int read(){//  int x=0;char ch=' ';int f=1;//  while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();//  if(ch=='-')f=-1,ch=getchar();//  while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();//  return x*f;int x;scanf("%d",&x);return x;}struct edge{    int to,next,w;}e[100001],e2[100001];int n,m,k,cnt,tot,tot2;int head[10001];int head2[10001];inline void addedge(int x,int y,int l){    e[++tot].to=y;e[tot].next=head[x];e[tot].w=l;head[x]=tot;}inline void addedge2(int x,int y,int l){    e2[++tot2].to=y;e2[tot2].next=head2[x];e2[tot2].w=l;head2[x]=tot2;}int dis[10001];queue<int> q1;void spfa(){    memset(dis,0x3f,sizeof(dis));    q1.push(n);    dis[n]=0;    while(!q1.empty()){        int x=q1.front();        q1.pop();        for(int i=head2[x];i;i=e2[i].next){            int u=e2[i].to;            if(dis[u]>dis[x]+e2[i].w){                dis[u]=dis[x]+e2[i].w;                q1.push(u);            }        }    }}struct node{    int id,f,g,h;    node(int _id,int _f,int _g,int _h):id(_id),f(_f),g(_g),h(_h){}    inline bool operator > (const node& y) const {        return (f==y.f)?g>y.g:f>y.f;    }};priority_queue<node,vector<node>,greater<node> > q;map<int,int> mp;int ans;void Astar(){    q.push(node(1,dis[1],0,dis[1]));    while(!q.empty()){        node now=q.top();        q.pop();        if(now.id==n){            if(!mp[now.g]){                mp[now.g]=1;                cnt++;            }        }        if(cnt==k){            ans=now.g;            return;        }        for(int i=head[now.id];i;i=e[i].next){            int u=e[i].to;            q.push(node(u,now.g+e[i].w+dis[u],now.g+e[i].w,dis[u]));        }    }}int main(){    n=read();m=read();k=read();    for(int i=1;i<=m;i++){        int x=read(),y=read(),l=read();        while(getchar()!='\n');        addedge(x,y,l);addedge2(y,x,l);    }    spfa();    Astar();    printf("%d",ans);    return 0;}