Til the Cows Come Home(最短路:dijkstra算法、Bellman-Ford算法) (J-0)

Til the Cows Come Home

Time Limit: 1000MS Memory Limit: 65536K

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.

Source
USACO 2004 November

题目解析:
意思是第一行输入两个数第一个数t是下面给出的行数,第二个数n是bessie 现在处在的地方的序号,下面的每一行给出三个数字,第一个是一个地标,第二个也是一个地标,第三个是这两个地方的距离(也就是长度length),最后要求出bessie从n地标走到1地标的最短路程(也就是最小路问题了),所以应该考虑到bellman算法,当然dijkstra算法(迪杰斯特拉算法)也可以实现,但Bellman-Ford比迪杰斯特拉算法更简单和同时也适用于分布式系统。但Bellman-Ford的时间复杂度是O(VE),这要比迪杰斯特拉算法慢。(V为顶点的个数,E为边的个数)(抄之百度)

下面是c++实现bellman算法的模板:

#include< iostream >
#include< cstdio >
using namespace std;
#define MAX 0x3f3f3f3f
#define N 1010
int nodenum, edgenum, original; //点,边,起点
typedef struct Edge //边
{
int u, v;
int cost;
}Edge;
Edge edge[N];
int dis[N], pre[N];
bool Bellman_Ford()
{
for(int i = 1; i <= nodenum; ++i) //初始化
dis[i] = (i == original ? 0 : MAX);
for(int i = 1; i <= nodenum - 1; ++i)
for(int j = 1; j <= edgenum; ++j)
if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛(顺序一定不能反~)
{
dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;
pre[edge[j].v] = edge[j].u;
}
bool flag = 1; //判断是否含有负权回路
for(int i = 1; i <= edgenum; ++i)
if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost)
{
flag = 0;
break;
}
return flag;
}
void print_path(int root) //打印最短路的路径(反向)
{
while(root != pre[root]) //前驱
{
printf("%d–>", root);
root = pre[root];
}
if(root == pre[root])
printf("%d\n", root);
}
int main()
{
scanf("%d%d%d", &nodenum, &edgenum, &original);
pre[original] = original;
for(int i = 1; i <= edgenum; ++i)
{
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);
}
if(Bellman_Ford())
for(int i = 1; i <= nodenum; ++i) //每个点最短路
{
printf("%d\n", dis[i]);
printf(“Path:”);
print_path(i);
}
else
printf(“have negative circle\n”);
return 0;
}

你们也可去看看这个百度百科,里面有pascal的模板 百度:bellman-ford算法

”二话不说“上代码:

#include <iostream>
#include"stdio.h"
#include"string.h"
using namespace std;
int t, n;
#define max 0x3f3f3f
int temp[2001];
struct node 
{
	int a;
	int b;
	int length;
}input[2001];
void bell()
{
	temp[1] = 0;
	for (int i = 0;i < n;i++)
	{
		for (int j = 0;j < t;j++)
		{
			if (temp[input[j].a] > temp[input[j].b] + input[j].length)
				temp[input[j].a] = temp[input[j].b] + input[j].length;
			else if (temp[input[j].b]>temp[input[j].a]+input[j].length)
				temp[input[j].b] = temp[input[j].a] + input[j].length;
		}
	}
}

int main()
{
	while (~scanf("%d%d", &t, &n))
	{
		for (int i = 0;i < t;i++)
		{
			scanf("%d%d%d", &input[i].a, &input[i].b, &input[i].length);
		}
		memset(temp, max, sizeof(temp));
		bell();
		cout << temp[n] << endl;
	}
}

上面bellman算法的程序里需要把一个函数temp[]里的除了temp[1]=0;以外的元素全部初始化为无穷大才行,而这个无穷大使用
#define max 0x3f3f3f里面的0x3f3f3f是很好的,
详情看这个0x3f3f3f3f…编程中无穷大常量的设置技巧
然后下面这个是dijkstra算法实现的代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int INF=99999999;                    //设为无穷大
int maps[1005][1005],v[1005],d[1005];  //v表示是否已经过遍历 d表示从源到点当前最短路
int n;

void Dijkstra(int s,int t)
{
    int i,j,k,mini;
    for(i=1;i<=n;i++)
        d[i]=INF;                      //除源点设为0距离外 其他先设为无穷大
    d[s]=0;
    for(i=1;i<=n;i++)                  //n点循环n次
    {                                                 
        mini=INF;
        k=-1;
        for(j=1;j<=n;j++)              //在所有未标记点中 选d值最小的点
        {
            if(!v[j] && d[j]<mini)
            {
                mini=d[k=j];
            }
        }
        v[k]=1;                         //标记节点
        if(k==t)
        {
            printf("%d\n",d[t]);
            return;
        }
        for(j=1;j<=n;j++)
        {
            if(!v[j] && d[k]+maps[k][j]<d[j])   //表示从k出发的点,对于所有边,更新相连点
            {
                d[j]=d[k]+maps[k][j];
            }
        }
    }
}

int main()
{
    int T,i,j,x,y,D;
    while(scanf("%d %d",&T,&n)!=EOF)
    {
        memset(v,0,sizeof(v));            //清除标记
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                maps[i][j]=INF;
            }
        }
        for(i=1;i<=T;i++)
        {
            scanf("%d %d %d",&x,&y,&D);
            if(maps[x][y]>D)               //可能有多条路,只记录最短的
                maps[x][y]=D,maps[y][x]=D;
        }
        Dijkstra(1,n);
    }
    return 0;
}                                          

cyd2014博客得来。

应该看得懂把,然后就是可以试着代一次例子进去计算一下每个步骤这样可以更好理解,大家加油丫丫丫丫啊

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值