牛慢跑
据说是(k)短路模板,要用(A^*),然而我不会。我是用拓扑排序加堆优化广搜水过去的。第一道完全靠自己做出来的紫题,调了两个小时,交了两遍。果然我还是太菜了。
正解的话,可以看红太阳的博客
题面
给出(n)个点(m)条边的有向无环图,求从(n)到(1)的前(k)条最短路的值。
(1≤N≤1000 ,1 <= M <= 10000 ,1≤K≤100)
输入格式:
第(1)行:三个以空格分隔的整数:(N,M)和(K).
第(2..M + 1)行:第(i + 1)行描述了使用三个以空格分隔的整数的下坡牛路径:(X_i,Y_i)和$D_i(1≤Di≤1000000) $
输出格式:
行(1..K):行(i)包含第(i)个最短路径的长度,如果不存在这样的路径,则为(-1)。如果多次出现最短路径长度,请务必在输出中多次列出。
输入样例
5 8 7
5 4 1
5 3 1
5 2 1
5 1 1
4 3 4
3 1 1
3 2 1
2 1 1
输出样例
1
2
2
3
6
7
-1
拓扑排序加堆优化广搜
以下是我的神奇做法。
要找前(k)条最短路,怎么找?我观察了一下样例的图,发现每个点的路径长度会被更新很多次,但都是由直接指向他的点更新来的(废话),也就是说,他前面的点怎样更新的我不关心,我只关心这个点前(k)条最短路的长度。
那直接用堆存一下就好了。
但是我们要保证他前面的点已经更新完了。前面说了这是一个有向无环图,自然想到拓扑排序。
但我之前犯了一个错误,它花费了我一个多小时的时间。这个题要求必须从(n)号点出发,但是有些点(n)号点到不了,它们一开始入度就为零。如果不把这些点的影响去掉,后面就会出错。果然我菜鸡的本质难以掩盖。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
long long read(){
long long x=0;int f=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return f?-x:x;
}
int n,m,k;
struct Dier{//前向星
int to,next,w;
}a[10004];
int head[1001],cnt;
void add(int x,int y,int z){//单向边
a[++cnt].to=y,a[cnt].next=head[x],a[cnt].w=z,head[x]=cnt;
}
priority_queue<int,vector<int>,greater<int> >q[1005];//小根堆
int in[1001],Q[1001],h,t;
// 入度 队列
int main(){
n=read(),m=read(),k=read();
for(int i=1,x,y,z;i<=m;++i){
x=read(),y=read(),z=read();
add(x,y,z),in[y]++;
}
//拓扑
for(int i=n;i;--i)
if(!in[i]) Q[++t]=i;
for(int i=1;i<=t;++i){
if(Q[i]==n) continue;//n号点的影响不应该去掉
int u=Q[i];
for(int i=head[u],v;v=a[i].to,i;i=a[i].next){
in[v]--;
if(!in[v]) Q[++t]=v;//斩草不除根,后面麻烦无穷
//只要不是从n号点直接或间接转移过来的入度都要去掉,因为他们会妨碍我们后面的入队
}
}
t=1,Q[1]=n;//初始化一下
q[n].push(0);
while(h<t){//广搜
int u=Q[++h],ls=0;
while(u!=1&&!q[u].empty()&&++ls<=k){//只取前k条就好
//保证1号点的距离不会被pop掉
for(int i=head[u],v;v=a[i].to,i;i=a[i].next)
q[v].push(q[u].top()+a[i].w);//更新距离
q[u].pop();
}
//计算入度一定要独立出来,不能和更新距离放在一起,因为那样会导致入度被减很多次
for(int i=head[u],v;v=a[i].to,i;i=a[i].next){
in[v]--;
if(!in[v]) Q[++t]=v;
}
}
while(!q[1].empty()&&k){//输出答案
printf("%d
",q[1].top()),q[1].pop(),k--;
}
for(int i=1;i<=k;++i) printf("-1
");//有可能并没有k条路可以走
return 0;
}
欢迎指正评论O(∩_∩)O~~