J - Til the Cows Come Home

J - 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
    Output
    90
    Hint
    INPUT DETAILS:

There are five landmarks.

OUTPUT DETAILS:

Bessie can get home by following trails 4, 3, 2, and 1.

题意

找最短路

dijkstra

图解

image
image
image

带注释模板(朴素版dijkstra)

点击查看代码
#include <iostream>
#include <cstring>

using namespace std;

const int N = 510;
int n, m;   //n代表点的数量,m代表边的数量 
int g[N][N];  //邻接矩阵-->储存的是点到点的距离 (即边长)
int dist[N];  //当前点到起点距离 
bool st[N];   //是否为最短路径 
int dijkstra(int a,int b){  //起点,终点
	
	memset(dist, 0x3f, sizeof dist);   //初始化用于判断是否找到
    memset(st, 0, sizeof st);
	dist[a]=0;   //第一个节点遍历同时初始化了下一层的所有节点距离
	//所以不用初始化st[1]=1 
	
	for(int i = 1; i <= n - 1; i ++ ){   //迭代一遍将所有点找到最短路径 
	//迭代次数为n-1的意思是在第n-1次时dist[n]的最短路径已经被确定 
		int  t = -1;
		for(int j = 1; j <= n; j ++){
			if(!st[j] && (t == -1 || dist[t] > dist[j])){
			//等于时不用更新 
			//找到(未找到最短路径的点)到(到起点距离(最近)的一个点 
			//该点此时到起点的距离可确定为最短路径 
				t = j;
			}
		}
		st[t]=1;  //已找到最短路径的点加入st中 
		for(int j = 1; j <= n; j ++){
			dist[j] = min(dist[j], dist[t] + g[t][j]);     //利用了贪心的思想:最短路径等于所有最短路径之和 
			//将起点到j(所有点)的距离更新为t(利用已确定最短路径的点)到j和起点到j的(较小值)
			//如果两点之间(没有联通)的话,距离应该是(无穷大),所以起点到j的距离不变 
		}
	}
	if (dist[b] == 0x3f3f3f3f) return -1; //没找到   //注意是4个3f 
	return dist[b]; 
}

int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m >> q;
     
    memset(g, 0x3f, sizeof g); 
     
    int a, b, c;
    while(m -- ){
        cin >> a >> b >> c;
        g[a][b] = min(g[a][b], c);    
        g[b][a] = min(g[b][a], c);
    }
    while(q --){
        int op;
        cin >> op;
        if(op == 2){
            cin >> a >> b >> c;
            g[a][b] = min(g[a][b], c); 
            g[b][a] = min(g[b][a], c);          
        }
        else{
            cin >> a >> b;
            cout << dijkstra(a,b) << endl;
        }
    }
     
    return 0;
}

堆优化版dijkstra

点击查看代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
int n,m;
const int N = 1e6 + 10;
int h[N], e[N], ne[N], idx, w[N];
int dist[N];
typedef pair<int, int> PII; 
bool st[N];

void add(int a,int b,int c){
	e[idx] = b,ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
} 

int dijkstra(){
	memset(dist, 0x3f, sizeof dist);
	priority_queue<PII, vector<PII>, greater<PII> > heap;  //定义小根堆  //>>尽量不要粘在一起 
	dist[1] = 0;  //距离记得初始化 
	heap.push({0,1});   //first存储距离,second存储序号  //因为排序默认以first优先
	
	while(heap.size()){    //队列不空 
		PII t = heap.top();   //注意数据类型
		heap.pop();   //出队
		
		int distance = t.first, ver = t.second;
		
		if(st[ver]) continue;   //如果该点已经被top过(就是ver最短路径)不用再进行下一步的更新最短路径 
		st[ver] = 1;           //why?因为heap.top()是离“源点 (不断更新)”最近的点所以是最短路径 
			
		for(int i = h[ver]; i != -1; i = ne[i]){   //遍历一遍ver直接连接的点 
			int j = e[i];
			if(dist[j] > dist[ver] + w[i]) {     
				//如果当前最短路径(源点到i)大于ver到i的距离,那么更新最短路径 
				dist[j] = dist[ver] + w[i];
				heap.push({dist[j], j});     //push进去是因为只是ver是最短路径,j不一定是最短路径, 
			} 
		}
	} 
	if(dist[n] == 0x3f3f3f3f)return -1;
	return dist[n];	 
}

原题代码

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

#define X first
#define Y second

typedef pair<int,int> pii;
typedef long long LL;
const char nl = '\n';
const int N = 1010;
const int M = 2e5+10;
int n,m;
int g[N][N],dist[N];
bool st[N];

void dijkstra(){
	memset(dist,0x3f,sizeof dist);
	dist[1] = 0;
	for(int i = 1; i <= n - 1; i ++ ){
		int t = -1;
		for(int j = 1; j <= n; j ++){
			if(!st[j] && (t == -1 || dist[t] > dist[j]))t = j;
		}
		st[t] = 1;
		for(int j = 1; j <= n; j ++ ){
			dist[j] = min(dist[j],dist[t] + g[t][j]);
		}
	}
	cout << dist[n] << nl;
}

void solve(){
	while(~scanf("%d%d",&m,&n)){
		memset(g,0x3f,sizeof g);
		memset(st,0,sizeof st);
		while(m --){
			int a,b,w;
			cin >> a >> b >> w;
			g[a][b] = min(g[a][b],w);
			g[b][a] = g[a][b];
		}
		dijkstra();
	}
}

int main(){
	//ios::sync_with_stdio(false);
	//cin.tie(0),cout.tie(0);

	solve();
}
posted @ 2023-02-22 22:38  Keith-  阅读(14)  评论(0编辑  收藏  举报