一本通 农场派对
【题目描述】
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;
}