题目描述
N(1≤N≤1000)头牛要去参加在某农场举行的一场编号为x(1≤x≤N)的牛的派对。有M(1≤M≤100000)条有向道路,每条道路长Ti(1≤Ti≤100);每头牛参加排队后都必须回到家,每头牛都会选择最短路。求这N头牛的最短路(一个来回)中最长的一条的长度。特别提醒:可能有权值不同的重边。
输入输出格式
输入格式:
第一行,3个空格分开的整数N,M,X。
第二行至第M+1行:3个用空格分开的整数Ai,Bi,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
输出样例#1:
10
提示信息
算法分析
简化题意:一个n个点,m条边的有向图,给出起点/终点(s),求
其中,d[i][j]表示i到j的最短路径。
方法1:dijkstra求任意两点间最短路,O(n(n+m)logm),超时。
方法2:Spfa求任意两点间最短路,O(n^2k)应该勉强通过。
方法3:dijkstra求原图单源最短路与反图单源最短路,O((n+m)log2m)或O(n^2),稳过。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
struct node{
int to;
int next;
int w;
}edge[200001];
int head[200001],d[2001],d1[2001];
int cnt,cow[3333],a[2001][2001];
int n,m,x,y,z,s;
void add_edge(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int dijkstra(int s)
{
priority_queue< P,vector<P>,greater<P> >q;
memset(d,0x3f,sizeof(d));
d[s]=0;
q.push(P(0,s));
while(!q.empty())
{
P p=q.top();
q.pop();
int u=p.second;
if(d[u]<p.first) continue;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(d[v]>d[u]+edge[i].w)
{
d[v]=d[u]+edge[i].w;
q.push(P(d[v],v));
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
int s;
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
cin>>x>>y>>z;
add_edge(x,y,z);
add_edge(y+n,x+n,z);
}
int u=0;
dijkstra(s);
for(int i=1;i<=n;i++)
{
d1[i]=d[i];
}
dijkstra(s+n);
for(int i=n+1;i<=2*n;i++) if(d1[i-n]<1000000&&d[i]<1000000)u=max(u,d1[i-n]+d[i]);
cout<<u;
return 0;
}