hdu 6201 transaction transaction transaction
https://vjudge.net/contest/184514#problem/H
题意:
一个商人为了赚钱,在城市之间倒卖商品。有n个城市,每个城市之间有且只有一条无向边连通。给出n个城市的货物的价格,比如A城市是a元,B城市是b元,那么在A买在B卖,赚的钱就是b - a,反之就是 a - b。商人走每条路也需要一定的花费。现在他需要选择某两个城市进行货物的倒卖,问他能获得的最大利润是多少。
思路:
建图的方式非常妙。我们把从A到B的边的权值定义为b - a - v(v为边的权值),从B到A的边的权值定义为a - b - v。依据这个从A到B再到C,就是b - a - v1 加上 c - b - v2,加起来就是c - a - v1 - v2,这样我们就可表示从任意城市到任意城市的距离了。
现在我们要求的就是任意两个城市之间的最大距离。树上最长路并不擅长,所以考虑用最短路求法进行求解。加一个超级源点和超级汇点,跑一遍最短路,就可以了,但是我们求的是最长路。。所以把边取反求最短路就ok了,开始用dijstra跑崩了,忘记了dij不能处理有负权边的图,所以跑了一遍spfa就过了。
这题的主要收获是建图,关键是抵消中间城市对结果的影响。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 7 const int inf = 0x3f3f3f3f; 8 9 struct edge 10 { 11 int from,to; 12 int cost; 13 }; 14 15 vector<edge> edges; 16 vector<int> v[100005]; 17 int nodev[100005]; 18 int dis[100010]; 19 bool vis[100010]; 20 21 void adde(int from,int to,int cost) 22 { 23 edge tmp; 24 25 tmp.from = from; 26 tmp.to = to; 27 tmp.cost = -cost; 28 29 edges.push_back(tmp); 30 31 int sz = edges.size(); 32 33 v[from].push_back(sz-1); 34 } 35 36 void init(int n) 37 { 38 for (int i = 0;i <= n;i++) v[i].clear(); 39 40 edges.clear(); 41 } 42 43 void spfa(void) 44 { 45 memset(vis,0,sizeof(vis)); 46 47 memset(dis,inf,sizeof(dis)); 48 49 queue<int> q; 50 51 q.push(0); 52 53 dis[0] = 0; 54 55 vis[0] = 1; 56 57 while (!q.empty()) 58 { 59 int u = q.front(); 60 61 q.pop(); 62 63 vis[u] = 0; 64 65 for (int i = 0;i < v[u].size();i++) 66 { 67 int id = v[u][i]; 68 69 int to = edges[id].to; 70 71 if (dis[to] > dis[u] + edges[id].cost) 72 { 73 dis[to] = dis[u] + edges[id].cost; 74 75 if (!vis[to]) 76 { 77 q.push(to); 78 vis[to] = 1; 79 } 80 } 81 } 82 83 } 84 } 85 86 int main() 87 { 88 int t; 89 90 scanf("%d",&t); 91 92 while (t--) 93 { 94 int n; 95 96 scanf("%d",&n); 97 98 init(n+1); 99 100 for (int i = 1;i <= n;i++) 101 { 102 scanf("%d",&nodev[i]); 103 } 104 105 for (int i = 1;i <= n - 1;i++) 106 { 107 int x,y,z; 108 109 scanf("%d%d%d",&x,&y,&z); 110 111 adde(x,y,nodev[y] - nodev[x] - z); 112 adde(y,x,nodev[x] - nodev[y] - z); 113 } 114 115 116 for (int i = 1;i <= n;i++) 117 { 118 adde(0,i,0); 119 adde(i,n+1,0); 120 } 121 122 spfa(); 123 124 printf("%d\n",-dis[n+1]); 125 126 127 //for (int i = 0;i <= n + 1;i++) printf("%d\n",dis[i]); 128 } 129 130 return 0; 131 }
康复训练中~欢迎交流!