关闭

POJ2387 Til the Cows Come Home(dijkstra + heap 或 SPFA)

标签: SPFAdijkstra+heap
234人阅读 评论(0) 收藏 举报
分类:
Til the Cows Come Home
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 33716   Accepted: 11416

Description

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

Hint

INPUT DETAILS: 

There are five landmarks. 

OUTPUT DETAILS: 

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

题目大意:

就是最短路的题.

解题思路:

今天刚好复习了一下dijkstra算法和bellman-ford,也顺便学习了他们各自的优化,以后比赛可以直接上优化版本。dijkstra是单源最短路径的常用算法,他从一个结点出发,然后每次寻找能到达其他没有访问过结点的最短距离,它的核心是松弛操作,然后更新距离.由于dijkstra主要是通过最短距离来更新的,所以我们可以使用优先队列来优化算法。队头的元素总是最小的距离,然后就可以以此更新结点。dijkstra算法比较适用于稠密图,也就是点比较多的图,但是它不能处理负权图,也就是图中存在负边,由于它松弛的特性,所以造就了如果存在负边,将会出现死循环。bellman-ford算法是按边来遍历松弛的,它可以用来判定负环,如果全部遍历完还可以松弛,那么证明存在负权。下面贴一下两种算法各自优化后的代码.

dijkstra + heap优化:

#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;

const int maxn = 3000;
int d[maxn]; //s到各个点的距离 
int done[maxn];
int p[maxn];
const int INF = 0x3fffff;
int m,n;

struct Edge
{
	int from,to,dist;
	Edge(int u,int v,int d):from(u),to(v),dist(d) {
	}
};

struct HeapNode
{
	int d,u;
	bool operator < (const HeapNode& rhs) const
	{
		return d > rhs.d;
	}
};

vector<Edge> edges; //边的信息 
vector<int> G[maxn]; //存储点的邻接边数 

void init(int n)
{
	for(int i=1;i<=n;i++)
	{
		G[i].clear();
		edges.clear();
	}
}

void AddEdge(int from,int to,int dist)
{
	int m;
	edges.push_back(Edge(from,to,dist));
	m = edges.size();
	G[from].push_back(m-1);
}

void dijkstra_heap(int s)
{
	priority_queue<HeapNode> Q;
	for(int i=1;i<=n;i++) d[i] = INF;
	d[s] = 0;
	memset(done,0,sizeof(done));
	HeapNode c;
	c.d = 0;
	c.u = s;
	Q.push(c);
	while(!Q.empty())
	{
		HeapNode x = Q.top(); Q.pop();
		int u = x.u; //新的结点
		if(done[u]) continue;
		done[u] = true;
		for(int i=0;i<G[u].size();i++)
		{
			Edge& e = edges[G[u][i]];
			if(d[e.to] > d[u] + e.dist)
			{
				d[e.to] = d[u] + e.dist;
				p[e.to]	= G[u][i];
				c.d = d[e.to];
				c.u = e.to;
				Q.push(c); //最小的边权和结点编号 
			}	
		} 
	}
}
int main()
{
	int s,e,dist,i;
	//freopen("1.txt","r",stdin);
	while(cin>>m>>n)
	{
		for(i=1;i<=m;i++)
		{
			cin>>s>>e>>dist;
			AddEdge(s,e,dist);
			AddEdge(e,s,dist);
		}
		dijkstra_heap(1);
		cout<<d[n]<<endl;
	}
} 

SPFA:

#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;

const int maxn = 3000;
bool inq[maxn];
int cnt[maxn];
int p[maxn]; //最短路中的上一条弧 
int d[maxn]; //s到各个点的距离 
const int INF = 0x3fffff;
int m,n;

struct Edge
{
	int from,to,dist;
	Edge(int u,int v,int d):from(u),to(v),dist(d) {
		
	}
};

vector<Edge> edges;
vector<int> G[maxn];

void init(int n)
{
	for(int i=1;i<=n;i++)
	{
		G[i].clear();
		edges.clear();
	}
}

void AddEdge(int from,int to,int dist)
{
	int m;
	edges.push_back(Edge(from,to,dist));
	m = edges.size();
	G[from].push_back(m-1);
}
              
bool SPFA(int s)
{
	queue<int> Q;
	memset(inq,false,sizeof(inq));
	memset(cnt,0,sizeof(cnt));
	for(int i=1;i<=n;i++) d[i] = INF;
	d[s] = 0; //源点到源点距离为0 
	inq[s] = true; //加入队列 
	Q.push(s);
	
	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		inq[u] = false;
		for(int i=0;i<G[u].size();i++)
		{
			Edge& e = edges[G[u][i]];
			if(d[u] < INF && d[e.to] > d[u] + e.dist)
			{
				d[e.to] = d[u] + e.dist;
				//cout<<d[e.to]<<endl;
				p[e.to] = G[u][i];
				if(!inq[e.to]) {
					Q.push(e.to); inq[e.to] = true;
					if(++cnt[e.to] > n) return false;
				}
			}
		}
	}
	return true;
}

int main()
{
	int s,e,dist,i;
	//freopen("1.txt","r",stdin);
	while(cin>>m>>n)
	{
		for(i=1;i<=m;i++)
		{
			cin>>s>>e>>dist;
			AddEdge(s,e,dist);
			AddEdge(e,s,dist);
		}
		SPFA(1);
		cout<<d[n]<<endl;
	}
} 


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:66888次
    • 积分:2401
    • 等级:
    • 排名:第17013名
    • 原创:178篇
    • 转载:15篇
    • 译文:0篇
    • 评论:6条
    最新评论