http://acm.uestc.edu.cn/#/problem/show/915
方老师的分身 II
Time Limit: 10000/5000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
方老师计算出了走路时间最长的那个分身所用的时间。于是有个特殊的分身(据说是方老师真身!)就不想如此古板的走最短路了!由于这个分身的特殊性,这个分身对于单向边可以当双向边走。但是这个特殊的分身想走最短路的同时,要求至少经过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的算法:
•就搞一个队列。一开始把起点压进去。每次弹出一个点,把和这个点有边直接相连的点都更新一遍,如果当前算出的距离小于之前算出的距离,就把值改成当前算的,然后看这个新点,如果不在队列中就压入队列。
•当队列为空时,就可以得到所有点到起点的距离。
代码:
1 #include <fstream> 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 7 using namespace std; 8 9 const int INF=0x7fffffff; 10 const int N=5005; 11 const int M=200005; 12 const int K=51; 13 queue<pair<int,int> > q; 14 int n,m,s,t,k;//s->begin; t->end. 15 int head[N],later[M],u[M],v[M],w[M]; 16 int dis[N][K];//到达第i个节点已经过k条边,此时的最短距离 17 bool b[N][K]; 18 19 void spfa(); 20 21 int main() 22 { 23 //freopen("D:\input.in","r",stdin); 24 //freopen("D:\output.out","w",stdout); 25 while(~scanf("%d%d",&n,&m)){ 26 memset(head,-1,sizeof(head)); 27 for(int i=0;i<m;i++){ 28 scanf("%d%d%d",&u[i],&v[i],&w[i]); 29 later[i]=head[u[i]]; 30 head[u[i]]=i; 31 u[i+m]=v[i]; 32 v[i+m]=u[i]; 33 w[i+m]=w[i]; 34 later[i+m]=head[u[i+m]]; 35 head[u[i+m]]=i+m; 36 } 37 scanf("%d%d%d",&s,&t,&k); 38 spfa(); 39 if(dis[t][k]==INF) puts("-1"); 40 else printf("%d ",dis[t][k]); 41 } 42 return 0; 43 } 44 void spfa(){ 45 for(int i=1;i<=n;i++) 46 for(int j=0;j<=K;j++) 47 dis[i][j]=INF; 48 dis[s][0]=0; 49 q.push(make_pair(s,0)); 50 while(!q.empty()){ 51 pair<int,int> tmp=q.front(); 52 q.pop(); 53 b[tmp.first][tmp.second]=0; 54 for(int i=head[tmp.first];i!=-1;i=later[i]){ 55 int tt=min(tmp.second+1,k);//边数大于k的都当做k来处理 56 if(dis[v[i]][tt]>dis[tmp.first][tmp.second]+w[i]){ 57 dis[v[i]][tt]=dis[tmp.first][tmp.second]+w[i]; 58 if(!b[v[i]][tt])//避免重复入队 59 q.push(make_pair(v[i],tt)),b[v[i]][tt]=1; 60 } 61 } 62 } 63 }