F - Til the Cows Come Home
Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible.
Farmer John's field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1..N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it.
Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.
Input
* Line 1: Two integers: T and N
* Lines 2..T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1..100.
Output
* Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.
Sample Input
5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100
Sample Output
90
给出t条路径和n个点,求从点n到点1的最短路径
Dijkstra算法(堆优化)
找到最短距离(d[i]表示起点s到点i的距离,最短距离即d[i]最小)已经确定的点(第一个是起点),从它出发更新与它相连的点的最短距离
(如果用二维数组存图要去重边,用链式向前星存法可以不用考虑这个问题)
spfa(SLF优化)
SLF:small label first,使用双向队列deque,如果dis[i]<dis[q.front()],那么将i点插入队首(先更新),否则插入队尾
从起点开始,对每个点进行松弛操作,更新dis,最后得到最短路径
稳定性比较差,可以用dij还是用dij
如果这道题中有负权边,因为是无向图,也就是说有负环,以上两种做法都解不了,但spfa可以判断有没有负环(当一个点重复进入队列n次( >n-1 )以上,就存在负环)
关于有向图中带负权边的问题
用spfa可以解决这个问题啦
然后发现如果把dij中if(q.front()==t)break(如果终点t最短距离已经确定,则退出),发现也可以搞定,但是显然按照dij的原理是不可能能处理负权边的,因为dij是从最短距离已经确定的点出发,这是前提,如果存在负权边,那么后续操作会使最短路径变小,破坏了前提
想了很久,发现去掉以上所说的话,其实堆优化的dij就相当于SLF优化的spfa了,只是队列用法不同而已
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<queue>
#include<bitset>
#include<utility>
#include<set>
#include<map>
#include<sstream>
#define INF 0x7f7f7f7f
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
const ll mod=1e18;
const int N=10005;
int t;
int n;
struct P{
int v;
int dis;
bool friend operator<(P a,P b){
return a.dis>b.dis;
}
};
struct Edge{
int y;
int nt;
int dis;
};
int head[N];
Edge e[N<<1];
int dis[N];
void add(int i,int x,int y,int w){
e[i].y=y;
e[i].dis=w;
e[i].nt=head[x];
head[x]=i;
}
void dij(){
memset(dis,127,sizeof(dis));
priority_queue<P> q;
P s;
s.v=n;
s.dis=0;
dis[n]=0;
q.push(s);
while(!q.empty()){
P x=q.top();
q.pop();
if(x.v==1)return;
for(int i=head[x.v];i!=-1;i=e[i].nt){
if(dis[x.v]+e[i].dis<dis[e[i].y]){
dis[e[i].y]=dis[x.v]+e[i].dis;
P a;
a.v=e[i].y;
a.dis=dis[a.v];
q.push(a);
}
}
}
}
int main(){
scanf("%d%d",&t,&n);
int x,y,w;
int k=0;
memset(head,-1,sizeof(head));
for(int i=0;i<t;i++){
scanf("%d%d%d",&x,&y,&w);
add(k,x,y,w);
k++;
add(k,y,x,w);
k++;
}
dij();
printf("%d\n",dis[1]);
return 0;
}
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<queue>
#include<bitset>
#include<utility>
#include<set>
#include<map>
#include<sstream>
#define INF 0x7f7f7f7f
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
const ll mod=1e18;
const int N=10005;
int t;
int n;
struct Edge{
int y;
int nt;
int dis;
};
int head[N];
Edge e[N<<1];
bool f[N];
int dis[N];
void add(int i,int x,int y,int w){
e[i].y=y;
e[i].dis=w;
e[i].nt=head[x];
head[x]=i;
}
int spfa(int s,int t){
memset(dis,127,sizeof(dis));
memset(f,0,sizeof(f));
deque<int> q;
dis[s]=0;
f[s]=1;
q.push_back(s);
while(!q.empty()){
int x=q.front();
q.pop_front();
f[x]=0;
for(int i=head[x];i!=-1;i=e[i].nt){
if(dis[x]+e[i].dis<dis[e[i].y]){
dis[e[i].y]=dis[x]+e[i].dis;
if(f[e[i].y]==0&&!q.empty()&&dis[e[i].y]<dis[q.front()]){
q.push_front(e[i].y);
}
else q.push_back(e[i].y);
f[e[i].y]=1;
}
}
}
}
int main(){
scanf("%d%d",&t,&n);
int x,y,w;
int k=0;
memset(head,-1,sizeof(head));
for(int i=0;i<t;i++){
scanf("%d%d%d",&x,&y,&w);
add(k,x,y,w);
k++;
add(k,y,x,w);
k++;
}
spfa(n,1);
printf("%d\n",dis[1]);
return 0;
}