题意
有一张无向无环连通图,点和边均有权值。一条路径的值等于路径上点的最大值加上边之和。
多次询问,两点之间路径最小值。
思路
每个点跑一遍dijkstra,判断是否取点加入点值。
代码
#include <bits/stdc++.h>
using namespace std;
namespace StandardIO {
template<typename T> inline void read (T &x) {
x=0;T f=1;char c=getchar();
for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T> inline void write (T x) {
if (x<0) putchar('-'),x=-x;
if (x>=10) write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Solve {
#define int long long
const int N=300;
const int INF=0x3f3f3f3f3f3f3f3f;
int n,m,k;
int G[N][N];
struct node {
int to,val;
node () {to=val=0;}
node (int x,int v) : to(x),val(v) {}
friend bool operator < (node a,node b) {
if (a.val!=b.val) return a.val>b.val;
return a.to>b.to;
}
};
int c[N];
int dis[N][N];
inline void dijkstra (int a) {
priority_queue<node> Q;
Q.push(node(a,0));
while (!Q.empty()) {
node now=Q.top();Q.pop();
if (dis[a][now.to]!=INF) continue;
dis[a][now.to]=now.val;
for (register int i=1; i<=n; ++i) {
if (c[i]>c[a]||G[now.to][i]==INF) continue;
Q.push(node(i,G[now.to][i]+dis[a][now.to]));
}
}
}
inline void MAIN () {
memset(G,0x3f,sizeof(G));
memset(dis,0x3f,sizeof(dis));
read(n),read(m),read(k);
for (register int i=1; i<=n; ++i) {
read(c[i]),G[i][i]=0;
}
for (register int i=1; i<=m; ++i) {
int x,y,z;
read(x),read(y),read(z);
G[x][y]=G[y][x]=min(G[x][y],z);
}
for (register int i=1; i<=n; ++i) dijkstra(i);
while (k--) {
int s,t,ans=INF;
read(s),read(t);
for (register int i=1; i<=n; ++i) {
if (c[i]>=c[s]&&c[i]>=c[t]) {
ans=min(ans,dis[i][s]+dis[i][t]+c[i]);
}
}
write(ans),putchar('
');
}
}
#undef int
}
int main () {
Solve::MAIN();
}