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的算法:

•就搞一个队列。一开始把起点压进去。每次弹出一个点,把和这个点有边直接相连的点都更新一遍,如果当前算出的距离小于之前算出的距离,就把值改成当前算的,然后看这个新点,如果不在队列中就压入队列。

•当队列为空时,就可以得到所有点到起点的距离。

代码:

 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\n",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 }
时间: 2024-08-24 15:46:57

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

UESTC_方老师的分身 II CDOJ 915

方老师的分身 II Time Limit: 10000/5000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方老师计算出了走路时间最长的那个分身所用的时间.于是有个特殊的分身(据说是方老师真身!)就不想如此古板的走最短路了!由于这个分身的特殊性,这个分身对于单向边可以当双向边走.但是这个特殊的分身想走最短路的同时,要求至少经过k条边. Input 有多组数据 第一行两个整数n,m(1≤n

UESTC 915 方老师的分身II --最短路变形

即求从起点到终点至少走K条路的最短路径. 用两个变量来维护一个点的dis,u和e,u为当前点的编号,e为已经走过多少条边,w[u][e]表示到当前点,走过e条边的最短路径长度,因为是至少K条边,所以大于K条边的当做K条边来处理就好了.求最短路的三个算法都可以做,我这里用的是SPFA,比较简洁. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #incl

uestc 方老师的分身 II

题意:求s到t走过边数大于k的最短路 思路:邻接表实现,用w[u][e]来维护(看的大牛博客),u表示当前点,e表示已经经过多少条边.感觉有点类似DP. 在边数大于k的处理上,发现还是使之等于k(K<=50),节省存储空间. spfa算法实现. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string>

UESTC 914 方老师的分身I Dijkstra

题意:求有向图的往返最短路的最长长度. 分析:求第一次到所有点的距离可以用一次Dijkstra求最短路求出来.考虑回来的路,想想就知道,从每个点回来的路即为将边的方向反转再求一次最短路后的结果. 所以此题为求两次最短路. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define Mod 100

UESTC 916 方老师的分身III --拓扑排序

做法: 如果有a<b的关系,则连一条a->b的有向边,连好所有边后,找入度为0的点作为起点,将其赋为最小的价值888,然后其所有能到的端点,价值加1,加入队列,删去上一个点,然后循环往复,直到队列为空,即每个点都赋予了一个权值为止. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #in

UESTC 917 方老师的分身IV --求欧拉路径

判断欧拉路径是否存在及求出字典序最小的欧拉路径问题(如果存在). 将字符串的第一个字母和最后一个字母间连边,将字母看成点,最多可能有26个点(a-z),如果有欧拉路径,还要判断是否有欧拉回路,如果有,则需要找一个字典序最小的点开始生成这条链,否则以起点开始生成链,起点即为出度比入度大1的点. 欧拉路径是否存在的判定: 1.全部点在一个联通块                               ----用并查集判联通块的数量2.所有点出度入度相等                      

POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)

Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10002   Accepted: 3302 Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given two strings A, B and one integer K, we define S,

【POJ 3415】Common Substrings 长度不小于k的公共子串的个数

长度不小于k的公共子串的个数,论文里有题解,卡了一上午,因为sum没开long long!!! 没开long long毁一生again--- 以后应该早看POJ里的Discuss啊QAQ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N = 200003; int t1[N], t2[N], c[

POJ 3415 Common Substrings(长度不小于k 的公共子串的个数--后缀数组+单调栈优化)

题意:给定两个字符串A 和B,求长度不小于k 的公共子串的个数(可以相同). 样例1: A="xx",B="xx",k=1,长度不小于k 的公共子串的个数是5. 样例2: A ="aababaa",B ="abaabaa",k=2,长度不小于k 的公共子串的个数是22. 思路: 如果i后缀与j后缀的LCP长度为L, 在L不小于K的情况下, 它对答案的贡献为L - K + 1. 于是我们可以将两个串连起来, 中间加个奇葩的分隔符