シルバーカウパーティー
時間制限:2000msメモリ制限:65536KB 64ビット整数IO形式:%lld Javaクラス名:メイン
Nの農場(1≤N≤1000)のそれぞれから1頭の牛が1..Nと番号付けされ、農場#X(1≤X≤N)で開催される大きな牛のパーティーに参加します。合計M(1≤M≤100,000)の一方向(一方通行の道路が農場のペアを接続します。道路iは、通過するのにTi(1≤Ti≤100)単位の時間を必要とします。
各牛はパーティーまで歩いて行き、パーティーが終わったら農場に戻らなければなりません。各牛は怠惰であるため、最短時間で最適なルートを選択します。牛の帰路は片道なので、元の帰路とは異なる場合があります。
すべての牛の中で、牛がパーティーまで歩いて戻ってくるのに費やす必要がある最長の時間はどれくらいですか?
入力
1行目:それぞれスペースで区切られた3つの整数:N、M、X
ライン2..M + 1:i + 1行目は、スペースで区切られた3つの整数Ai、Bi、Tiで道路iを表します。説明されている道路は、農場Aiから農場Biまで走っており、Ti時間単位で横断する必要があります。
出力
1行目:1つの整数: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
トピックの主なアイデア:老牛にはパーティーがあり、各牛は牛舎(1からn)に住んでいます。すべての牛の中で老牛との間の最長の旅を見つけるように頼んでください(牛泥棒JBは怠惰ですが非常に賢いので、行くか来るかを問わず最短経路です)。ポイントの数、側面の数、および老牛の位置を表す3つの数字を入力します。これは有向グラフmap[a][b]不一定等于map[b][a]
です。
分析:最初に、DIJの考えによれば、老牛の位置Xから始めて、他のポイントへの最短経路を見つけます。次に、隣接行列を転置し(transpose map [] [])、XからDIJを再開し、他の点からXへの最短経路を見つけます。最大のパスを取得するために、最短パスを記録する2つの配列を追加すれば完了です。
#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
using namespace std;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
int map[maxn][maxn];
int dis[maxn];
int vis[maxn];
int dd[maxn];
int n,m,x;
int a,b,time;
void dij(){
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
dis[x]=0;
for( int i=1 ; i<=n ; i++ ){
int u = -1;
for( int j=1 ; j<=n ; j++ ){
if(!vis[j]&&(u==-1||dis[j]<dis[u])){
u=j;
}
}
vis[u]=1;
for( int j=1 ; j<=n ; j++ ){
if(dis[j]>dis[u]+map[u][j]){
dis[j] = dis[u] + map[u][j];
}
}
}
}
int main(){
while(~scanf("%d%d%d",&n,&m,&x)){
memset(map,INF,sizeof(map));
while(m--){
scanf("%d%d%d",&a,&b,&time);
map[a][b]=time;
}
dij();
for( int i=1 ; i<=n ; i++ ){
dd[i]=dis[i];
}
for( int i=1 ; i<=n ; i++ ){
for( int j=i+1 ; j<=n ; j++ ){
map[i][j] = map[i][j] ^ map[j][i];
map[j][i] = map[i][j] ^ map[j][i];
map[i][j] = map[i][j] ^ map[j][i];
}
}
dij();
int max=-1;
for( int i=1 ; i<=n ; i++ ){
if((dd[i]+dis[i])>max){
max = dd[i]+dis[i];
}
}
printf("%d\n",max);
}
return 0;
}