小S 想要从某地出发去同学k的家中参加一个party,但要有去有回。他想让所用的
时间尽量的短。但他又想知道从不同的点出发,来回的最短时间中最长的时间是多
少,这个任务就交给了你
第一行三个正整数n, m, k(n是节点个数,m是有向边的条数,k是参加聚会的地点
编号)( 1 ≤ n ≤ 1000 ,1 ≤ m ≤ 100,000)
第二行..m + 1行每行3个整数x,y,w 代表从x到y需要花w的时间 0
输出从不同的节点出发的最短时间中最长的时间
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
分类标签 Tags 点此展开
#include
using namespace std;
#include
#include
struct Edge{
int u,v,w,next;
};
#include
Edge edge[100001<<1],edge1[100001<<1];//注意边表一定要开到n*n的大小,才可以不越界
const int INF=0x7fffffff; // 赋值最大值,0x7(再加上七个f)就是无限数,这个题虽然w《=100,但是边的数目很多时,仍会超过999999,所以要赋这个数
int head[100001],visit[100001],head1[100001],visit1[100001];
int dis[100001],dis1[100001],dis2[100001];
int n,m,k;
void input()
{
scanf("%d%d%d",&n,&m,&k);///n ge dian
for(int i=1;i<=n;++i)
{
dis[i]=INF;
dis1[i]=INF;
}
int t=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
edge[++t].w=INF;
edge1[t].w=INF;
}
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&edge[i].v,&edge[i].u,&edge[i].w);
edge[i].next=head[edge[i].u];
if(edge[i].u==k)
dis[edge[i].v]=edge[i].w;
head[edge[i].u]=i;
edge1[i].u=edge[i].v;
edge1[i].v=edge[i].u;
edge1[i].w=edge[i].w;
edge1[i].next=head1[edge1[i].u];
head1[edge1[i].u]=i;
if(edge1[i].u==k)
dis1[edge1[i].v]=edge1[i].w;
}
}
void dijstra()
{
dis[k]=0;
visit[k]=1;
for(int i=1;i<=n-1;i++)
{
int p=0,min1=INF;
for(int j=1;j<=n;++j)
{
if(!visit[j]&&dis[j]
{
p=j;
min1=dis[j];
}
}
if(p==0) break;
visit[p]=1;
for(int l=head[p];l!=0;l=edge[l].next)
{
if(!visit[edge[l].v]&&edge[l].w+dis[edge[l].u]
{
dis[edge[l].v]=edge[l].w+dis[edge[l].u];
}
}
}
}
void dijstra1()
{
dis1[k]=0;
visit1[k]=1;
for(int i=1;i<=n-1;i++)
{
int p=0,min1=INF;
for(int j=1;j<=n;++j)
{
if(!visit1[j]&&dis1[j]
{
p=j;
min1=dis1[j];
}
}
if(p==0) break;
visit1[p]=1;
for(int l=head1[p];l!=0;l=edge1[l].next)
{
if(!visit1[edge1[l].v]&&edge1[l].w+dis1[edge1[l].u]
{
dis1[edge1[l].v]=edge1[l].w+dis1[edge1[l].u];
}
}
}
}
int main()
{
input();
dijstra();
dijstra1();
for(int i=1;i<=n;++i)
dis2[i]=dis[i]+dis1[i];
sort(dis2+1,dis2+n+1);
printf("%d",dis2[n]);
return 0;
}