一本通 农场派对

【题目描述】
N(1≤N≤1000)头牛要去参加一场在编号为 x(1≤x≤N) 的牛的农场举行的派对。有 M(1≤M≤100000) 条有向道路,每条路长 Ti(1≤Ti≤100);每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这 N头牛的最短路径(一个来回)中最长的一条的长度。 特别提醒:可能有权值不同的重边。
【输入】
第 1行:3 个空格分开的整数 N,M,X;
第 2…M 行:3 个空格分开的整数 Ai,Bi,Ti ​​,表示有一条从 Ai 到 Bi的路,长度为 Ti。
【输出】
一行一个数,表示最长最短路的长度(<231-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
模板题,有向边,使用两次dijk搜一下就可以了,存一个图,一个反转后的图,从各个农场到x农场,然后再从x农场到各个农场的最短路。
然后单源最短路径得出.

#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f;
int n,m,x,e[1100][1100],book[1100],dis1[1100],minn;
int ee[1100][1100],dis2[1100];
void dijk1()
{
	int i,j,u;
	memset(book,0,sizeof(book));
	for (i=1; i<=n; i++)
		dis1[i]=e[x][i];
	book[x]=1;

	for (i=1; i<=n; i++) //n-1
	{
		minn=inf;
		for (j=1; j<=n; j++)
		{
			if (!book[j]&&dis1[j]<minn)
			{
				minn=dis1[j];
				u=j;
			}
		}
		book[u]=1;
		for (j=1; j<=n; j++)
		{
			if (e[u][j]<inf&&!book[j])
				if (dis1[j]>dis1[u]+e[u][j])
					dis1[j]=dis1[u]+e[u][j];
		}
	}
	return;
}
void dijk2()
{
	int i,j,u;
	memset(book,0,sizeof(book));
	for (i=1; i<=n; i++)
		dis2[i]=ee[x][i];
	book[x]=1;

	for (i=1; i<=n; i++) //n-1
	{
		minn=inf;
		for (j=1; j<=n; j++)
		{
			if (!book[j]&&dis2[j]<minn)
			{
				minn=dis2[j];
				u=j;
			}
		}
		book[u]=1;
		for (j=1; j<=n; j++)
		{
			if (ee[u][j]<inf&&!book[j])
				if (dis2[j]>dis2[u]+ee[u][j])
					dis2[j]=dis2[u]+ee[u][j];
		}
	}
	return;
}
int main()
{
	int i,j,t,a,b;
	scanf("%d%d%d",&n,&m,&x);
	memset(book,0,sizeof(book));
	for (i=1; i<=n; i++)
		for (j=1; j<=n; j++)
			if (i==j)
				e[i][j]=ee[i][j]=0;
			else
				e[i][j]=ee[i][j]=inf;
	for (i=1; i<=m; i++)
	{
		scanf("%d%d%d",&a,&b,&t);
		e[a][b]=t;
		ee[b][a]=t;
	}
	dijk1();
	dijk2();
	int maxx=-1;
	for (i=1; i<=n; i++)
	{
		if (maxx<dis1[i]+dis2[i])
			maxx=dis1[i]+dis2[i];
	}
	printf("%d\n",maxx);
	return 0;
}
posted @ 2020-12-06 15:42  索饮  阅读(103)  评论(0编辑  收藏  举报