P1218 过路费
奋斗了两天,终于写过了这道题......
这道题不仅要求最短路,还要加上路径上最大的点权;
先用结构体记录点的序号和点的值这是毋庸置疑的;再用另外一个数组来记录当前点权也是可以理解的,毕竟后面要排序;将点权从小到大排序也是为了求最短路;然后再输入每条边的权值;min是为了保证两点之间有重复的边而取最小值;n代表两边的最小值,l就加上了点权;Floyd先将两点相同时就是自己的点权;将点权从小到大枚举,用t来记录此时所对应的原来的序号;两边之间的最短路就用普通的方法,加上点权就要加上中间量k值的点权和两端i,j点权的最大值;最后输出就行了;
#include <bits/stdc++.h> using namespace std; inline int read() { int x = 0,ff = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x<<1) + (x<<3) + (ch ^ 48); ch = getchar(); } return x * ff; } inline void write(int x) { if(x < 0) putchar('-'),x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } int a,b,c,m[1111],n[1100][1100],l[1010][1010]; struct node { int id; int v; } d[1111]; bool my(node x,node y) { return x.v < y.v; } void Floyd() { for(int i = 1; i <= a; ++i) l[i][i] = m[i]; for(int k = 1; k <= a; ++k) { int t = d[k].id; for(int i = 1; i <= a; ++i) { for(int j = 1; j <= a; ++j) { n[i][j] = min(n[i][j],n[i][t] + n[t][j]); l[i][j] = min(l[i][j],n[i][j] + max(d[k].v,max(m[i],m[j]))); } } } } int main() { memset(n,0x3f,sizeof(n)); memset(l,0x3f,sizeof(l)); a = read(); b = read(); c = read(); for(int i = 1; i <= a; ++i) { d[i].v = read(); d[i].id = i; m[i] = d[i].v; } sort(d + 1,d + a + 1,my); for(int i = 1; i <= b; ++i) { int x,y,v; x = read(); y = read(); v = read(); n[x][y] = min(n[x][y],v); n[y][x] = min(n[y][x],v); } Floyd(); for(int i = 1; i <= c; ++i) { int x,y; x = read(); y = read(); write(l[x][y]); putchar('\n'); } return 0; }