题意:一棵树,有点权,边权,问选择2个点,即abs(a[i]-a[j]) - (这两点经过的边权) 最大
思路: 我们假设买为 x ,卖为y ,路径消耗为z ,即 x- (y+z)最大,即-(x-(y+z))最小,
我们增加一个0点,他到每个点的距离为- 该点权值 (即买书的钱
增加个n+1点,到每个点的距离为该点权值(即卖书的到的钱
0到n+1跑个最短路即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=3e6+10;; 4 const int INF=1000000; 5 int n,m,dis[N],head[N],len; 6 bool vis[N]; 7 int b[N]; 8 9 struct edge 10 { 11 int to,val,next; 12 }e[N]; 13 14 void add(int from,int to,int val) 15 { 16 e[len].to=to; 17 e[len].val=val; 18 e[len].next=head[from]; 19 head[from]=len++; 20 } 21 struct point 22 { 23 int val,id; 24 point(int id,int val):id(id),val(val){} 25 bool operator <(const point &x)const{ 26 return val>x.val; 27 } 28 }; 29 void dijkstra(int s) 30 { 31 memset(vis,0,sizeof(vis)); 32 for(int i=0;i<N;i++) 33 dis[i]=INF; 34 priority_queue<point> q; 35 q.push(point(s,0)); 36 dis[s]=0; 37 while(!q.empty()) 38 { 39 int cur=q.top().id; 40 q.pop(); 41 if(vis[cur]) continue; 42 vis[cur]=true; 43 for(int i=head[cur];i!=-1;i=e[i].next) 44 { 45 int id=e[i].to; 46 if(!vis[id] && dis[cur]+e[i].val < dis[id]) 47 { 48 dis[id]=dis[cur]+e[i].val; 49 q.push(point(id,dis[id])); 50 } 51 } 52 } 53 } 54 55 int main() 56 { 57 int t; 58 cin>>t; 59 while(t--) 60 { 61 scanf("%d",&n); 62 len=0; 63 for(int i=1;i<=n;i++) scanf("%d",&b[i]); 64 memset(head,-1,sizeof(head)); 65 for(int i=1;i<n;i++) 66 { 67 int from,to,val; 68 scanf("%d%d%d",&from,&to,&val); 69 add(from,to,val); 70 add(to,from,val); 71 } 72 for(int i=1;i<=n;i++){ 73 add(0,i,-b[i]); 74 add(i,0,-b[i]); 75 } 76 for(int i=1;i<=n;i++){ 77 add(n+1,i,b[i]); 78 add(i,n+1,b[i]); 79 } 80 dijkstra(0); 81 printf("%d ",abs(dis[n+1])); 82 } 83 return 0; 84 85 }