Silver Cow Party(银牛派对、dijkstra)

描述

来自N个农场(1≤N≤1000)的一头奶牛,编号为1.N将参加在农场#X(1 ≤ X ≤ N)举行的大型奶牛派对。总共M(1≤M≤100,000)单向(单向道路连接成对的农场;道路i需要Ti(1≤ Ti≤100)的时间单位才能穿越。

每头奶牛必须走到派对上,当派对结束后,回到她的农场。每头奶牛都很懒惰,因此可以在最短的时间内选择最佳路线。奶牛的返回路线可能与她原来的聚会路线不同,因为道路是单向的。

在所有奶牛中,奶牛必须花在步行到聚会和回来的最长时间是多少?

输入

第 1 行:分别有三个空格分隔的整数:NM 和 X
行 2。M+1:i+1 行用三个空格分隔的整数描述道路 iAiBi 和 Ti。所描述的道路从农场Ai延伸到农场Bi,需要Ti时间单位才能穿越。

输出

第 1 行:一个整数:任何一头奶牛必须行走的最长时间。

示例输入

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

示例输出

10

分析:求的是来回距离和最大,这个题不算难。要说难的话,难在求其他点到“派对”的距离。

其他的就是套模板了。但是我还是做了一下午,我把一个i打成1了,这个错误找了一下午......被自己蠢到了。我这个代码看着长,但是很容易理解(其实是题简单【doge】)。

#include<iostream>
#include<cstring>
#include<algorithm>
#define MAXN 3010
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m,t;
int dist[MAXN], vis[MAXN],dist1[MAXN];
int g[MAXN][MAXN];
void dijkstra() {
	memset(vis, 0, sizeof(vis));//将标记数组vis清零
	for (int i = 1; i <= n; i++)
		dist[i] = g[t][i];
	vis[t] = 1;
	for (int i = 1; i <= n - 1; i++) {//重复进行n-1次
		int pos = -1;//找到未标记结点中dist最小的
		for (int j = 1; j <= n; j++)
			if (vis[j] == 0 && (pos == -1 || dist[j] < dist[pos]))
				pos = j;
		vis[pos] = 1;
		//用全局最小值点pos更新其他结点
		for (int j = 1; j <= n; j++)
			if(vis[j]==0)
			dist[j] = min(dist[j], dist[pos] + g[pos][j]);
	}
}

void dijkstra1() {
	memset(vis, 0, sizeof(vis));//将标记数组vis清零
	for (int i = 1; i <= n; i++)
		dist1[i] = g[t][i];
	vis[t] = 1;
	for (int i = 1; i <= n - 1; i++) {//重复进行n-1次
		int pos = -1;//找到未标记结点中dist最小的
		for (int j = 1; j <= n; j++)
			if (vis[j] == 0 && (pos == -1 || dist1[j] < dist1[pos]))
				pos = j;
		vis[pos] = 1;
		//用全局最小值点pos更新其他结点
		for (int j = 1; j <= n; j++)
			if(vis[j]==0)
			dist1[j] = min(dist1[j], dist1[pos] + g[pos][j]);
	}
}
int main()
{
	scanf("%d %d %d", &n, &m,&t);
	memset(g, 0x3f, sizeof(g));
	for (int i = 1; i <= n; i++)
		g[i][i] = 0;
	for (int i = 1; i <= m; i++)
	{
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		g[x][y] = min(g[x][y], z);
	}
	dijkstra();//x作为起点;得到的dist为x到每个点的距离
	for (int i = 1; i <= n; i++)//转换距离,获得其他点到m的距离。这样,不用求其他点到x的距离,求x到其他点的距离
		                         //不理解的话举个例子,a[1][2]=3;a[2][1]=4;交换之后1到2的距离可以用a[2][1]表示。
		                        //不这样的话,要求每个点到x的距离吧。
		for (int j = i+1; j <= n; j++)
		{
			int temp = g[i][j];
			g[i][j] = g[j][i];
			g[j][i] = temp;
		}
	dijkstra1();
	int maxn = 0;
	for (int i = 1; i <= n; i++)
	{
		if (dist[i]+dist1[i] == 0)
			continue;
		if (maxn< dist[i]+dist1[i])
			maxn = dist[i]+dist1[i];
	}
	printf("%d", maxn);
	return 0;
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值