cdoj915-方老师的分身 II (长度不小于k的最短路)【spfa】

时间:2023-03-10 05:24:53
cdoj915-方老师的分身 II                         (长度不小于k的最短路)【spfa】

http://acm.uestc.edu.cn/#/problem/show/915

方老师的分身 II

Time Limit: 10000/5000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

方老师计算出了走路时间最长的那个分身所用的时间。于是有个特殊的分身(据说是方老师真身!)就不想如此古板的走最短路了!由于这个分身的特殊性,这个分身对于单向边可以当双向边走。但是这个特殊的分身想走最短路的同时,要求至少经过k条边。

Input

有多组数据

第一行两个整数n,m(1≤n≤5000,1≤m≤100000)表示有n个教室,m条边。

接下来m行,每行3个数,u,v,t。表示u,v间有一条长度为t的边。

最后一行三个整数s,t,k,表示起点、终点、至少经过k(k≤50)条边。

Output

一个整数,表示最短路径长度。如果无解输出−1。

每组数据占一行。

Sample input and output

Sample Input Sample Output
4 4
1 2 1
2 3 2
1 3 100
3 4 1
1 3 5
7

题解:在基础的最短路上加了限制条件:不小于k的长度。于是可以在距离数组dis上加一维状态,dis[i][j]表示到达节点i已经过j条边的最短路,达到目的。这里采用的是spfa,dijkstra也可。

这里简单说下spfa的算法:

•就搞一个队列。一开始把起点压进去。每次弹出一个点,把和这个点有边直接相连的点都更新一遍,如果当前算出的距离小于之前算出的距离,就把值改成当前算的,然后看这个新点,如果不在队列中就压入队列。
•当队列为空时,就可以得到所有点到起点的距离。
代码:
 #include <fstream>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue> using namespace std; const int INF=0x7fffffff;
const int N=;
const int M=;
const int K=;
queue<pair<int,int> > q;
int n,m,s,t,k;//s->begin; t->end.
int head[N],later[M],u[M],v[M],w[M];
int dis[N][K];//到达第i个节点已经过k条边,此时的最短距离
bool b[N][K]; void spfa(); int main()
{
//freopen("D:\\input.in","r",stdin);
//freopen("D:\\output.out","w",stdout);
while(~scanf("%d%d",&n,&m)){
memset(head,-,sizeof(head));
for(int i=;i<m;i++){
scanf("%d%d%d",&u[i],&v[i],&w[i]);
later[i]=head[u[i]];
head[u[i]]=i;
u[i+m]=v[i];
v[i+m]=u[i];
w[i+m]=w[i];
later[i+m]=head[u[i+m]];
head[u[i+m]]=i+m;
}
scanf("%d%d%d",&s,&t,&k);
spfa();
if(dis[t][k]==INF) puts("-1");
else printf("%d\n",dis[t][k]);
}
return ;
}
void spfa(){
for(int i=;i<=n;i++)
for(int j=;j<=K;j++)
dis[i][j]=INF;
dis[s][]=;
q.push(make_pair(s,));
while(!q.empty()){
pair<int,int> tmp=q.front();
q.pop();
b[tmp.first][tmp.second]=;
for(int i=head[tmp.first];i!=-;i=later[i]){
int tt=min(tmp.second+,k);//边数大于k的都当做k来处理
if(dis[v[i]][tt]>dis[tmp.first][tmp.second]+w[i]){
dis[v[i]][tt]=dis[tmp.first][tmp.second]+w[i];
if(!b[v[i]][tt])//避免重复入队
q.push(make_pair(v[i],tt)),b[v[i]][tt]=;
}
}
}
}