这道题是今下午练习赛的题目,感觉题目很好。
题意大致是,每头牛要从起点去终点,再从终点回到起点,并且从起点到终点和从终点到起点为单向路径,求所有牛里面 起点到终点+终点到起点 的最短路径里面最大值为多少。
大致思路为:用两次dikstra算法分别求起点到终点和终点到起点的最短距离,因为是单向的所以可以通过转置进行转换,否则还要另开一个数组一个一个模拟所有点到目标,通过转置就可以把路径的方向更改。
AC代码(63ms,还是很快的):
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 1100;
int a[N][N], dis[N], sum[N], visit[N];
int n, m, x;
const int inf = 1100000;
int main()
{
while(scanf("%d %d %d", &n, &m, &x)!=EOF)
{
memset(sum,0,sizeof(sum));
memset(a,127,sizeof(a));
for(int i=0;i<m;i++)
{
int c, b, w;
scanf("%d %d %d", &c, &b, &w);
a[c][b]=w;
}
for(int i=1;i<=n;i++)
{
dis[i]=a[x][i];
}
memset(visit,0,sizeof(visit));
visit[x]=1;
for(int i=1;i<n;i++)//Dijkstra算法求终点到各个点的最短路径
{
int u, Min=inf;
for(int j=1;j<=n;j++)
{
if(visit[j]==0&&dis[j]<Min)
{
u=j;
Min=dis[j];
}
}
if(Min==inf) break;
visit[u]=1;
for(int j=1;j<=n;j++)
{
if(visit[j]==0&&dis[u]+a[u][j]<dis[j])
{
dis[j]=dis[u]+a[u][j];//dis[j]表示终点到j点的最短距离
}
}
}
for(int i=1;i<=n;i++)
{
if(dis[i]!=inf)
{
sum[i]+=dis[i];
}
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
int tmp;
tmp=a[i][j],a[i][j]=a[j][i],a[j][i]=tmp;//交换单向路径的方向
}
}
for(int i=1;i<=n;i++)
{
dis[i]=a[x][i];
}
memset(visit,0,sizeof(visit));
visit[x]=1;
for(int i=1;i<n;i++)//Dijkstra算法求起点到各个点的最短路径
{
int u, Min=inf;
for(int j=1;j<=n;j++)
{
if(visit[j]==0&&dis[j]<Min)
{
u=j;
Min=dis[j];
}
}
if(Min==inf) break;
visit[u]=1;
for(int j=1;j<=n;j++)
{
if(visit[j]==0&&dis[u]+a[u][j]<dis[j])
{
dis[j]=dis[u]+a[u][j];//dis[j]表示起点到j点的最短距离
}
}
}
for(int i=1;i<=n;i++)
{
if(dis[i]!=inf)
{
sum[i]+=dis[i];
}
}
int Max=-1;
for(int i=1;i<=n;i++)
{
Max=max(Max,sum[i]);
}
printf("%d\n",Max);
}
return 0;
}