zoukankan      html  css  js  c++  java
  • 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)
     

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

    Input

    有多组数据

    第一行两个整数nm1n50001m100000)表示有n个教室,m条边。

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

    最后一行三个整数stk,表示起点、终点、至少经过kk50)条边。

    Output

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

    每组数据占一行。

    Sample input and output

    Sample InputSample 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 }
  • 相关阅读:
    2016年3月11日Android学习日记
    JVM加载class文件的原理机制(转)
    2016年3月11日Android实习日记
    2016年3月10日Android实习日记
    2016年3月9日Android实习日记
    2016年3月8日Android实习日记
    2016年3月4日Android实习笔记
    2016年3月3日android实习笔记
    2016年3月1日Android实习笔记
    Android疑问小结
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4618705.html
Copyright © 2011-2022 走看看