[2018.10.17 T2] 最優路線
阿新 • • 發佈:2018-11-09
暫無連結
最優路線
【題目描述】
一個 個點 條邊的無重邊無自環的無向圖,點有點權,邊有邊權,定義一條路徑的權值為路徑經過的點權的最大值乘邊權最大值。求任意兩點間的權值最小的路徑的權值。
【輸入格式】
第一行兩個整數
,分別表示無向圖的點數和邊數。
第二行
個正整數,第
個正整數表示點
的點權。
接下來
行每行三個正整數
,分別描述一條邊的兩個端點和邊權。
【輸出格式】
行每行 個整數,第 行第 個整數表示從 到 的路徑的最小權值,如果從 不能到達 ,則該值為 。特別地,當 時輸出 。
【樣例 1】
path. in
3 3
2 3 3
1 2 2
2 3 3
1 3 1
path.out
0 6 3
6 0 6
3 6 0
【樣例 2】
見選手目錄下 path. in/path.ans。
【資料範圍與約定】
對於
的資料,
。
對於
的資料,
。
對於
的資料,
,邊權和點權不超過
。
題解
先考慮 分做法, 表示 到 ,路徑上最長邊長度為 時最大點點權的最小值,類似 更新一下就可以做到 。
事實上,我們不需要那麼麻煩, 表示 到 路徑上最長邊的最小值,使用 來更新,但是列舉中繼點 的時候我們要按點權從小到大列舉,這樣 到 路徑上點權最大的點就一定是 中的一個,於是便可以更新答案為 。
程式碼
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=505;
struct sd{int val,id;}pt[M];
bool operator<(sd a,sd b){return a.val<b.val;}
int val[M],mx[M][M],n,m;
ll ans[M][M];
void in()
{
scanf("%d%d",&n,&m);
memset(mx,127,sizeof(mx));
for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)if(i!=j)ans[i][j]=LONG_LONG_MAX;
for(int i=1;i<=n;++i)scanf("%d",&val[i]),pt[i]=(sd){val[i],i};
for(int i=1,a,b,c;i<=m;++i)scanf("%d%d%d",&a,&b,&c),mx[a][b]=mx[b][a]=c,ans[a][b]=ans[b][a]=1ll*max(val[a],val[b])*mx[a][b];
}
void ac()
{
sort(pt+1,pt+1+n);
for(int k=1;k<=n;++k)for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
if(mx[i][j]>max(mx[i][pt[k].id],mx[pt[k].id][j]))
mx[i][j]=max(mx[i][pt[k].id],mx[pt[k].id][j]),ans[i][j]=min(ans[i][j],1ll*mx[i][j]*max(pt[k].val,max(val[i],val[j])));
for(int i=1;i<=n;++i,putchar(10))for(int j=1;j<=n;++j)printf("%lld ",ans[i][j]==LONG_LONG_MAX?-1:ans[i][j]);
}
int main(){in(),ac();}