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 }

 

posted @ 2017-09-11 22:50  qrfkickit  阅读(150)  评论(0编辑  收藏  举报