HDU 6201【最長路+SPFA轉化為流問題求解***】
阿新 • • 發佈:2018-04-22
.com ID printf head eof namespace 題意 scanf pop
題意: 給出一棵生成樹,每個點有一個權值,代表商品的售價,樹上每一條邊上也有一個權值,代表從這條邊經過所需要的花費。現在需要你在樹上選擇兩個點,一個作為買入商品的點,一個作為賣出商品的點,當然需要考慮從買入點到賣出點經過邊的花費。使得收益最大。允許買入點和賣出點重合,即收益最小值為0.
這個題不用樹形DP也能求,實在是太巧妙。貼一個別人的解法
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; const int MAXN = 500010; const int INF = 2000; typedef struct node { int from; int to; int value; int next; }node; node edge[MAXN]; int head[MAXN], cnt, n; int d[MAXN], vis[MAXN]; void addedge(int from, int to, int value) { edge[cnt].from = from; edge[cnt].to = to; edge[cnt].value = value; edge[cnt].next = head[from]; head[from] = cnt++; } void spfa(int s, int e) { queue<int> mq; mq.push(s); vis[s] = 1; d[s] = 0; while (!mq.empty()) { int front = mq.front(); mq.pop(); vis[front] = 0; for (int i = head[front]; i != -1; i = edge[i].next) { int to = edge[i].to; int value = edge[i].value; if (d[to] < d[front] + value) { d[to] = d[front] + value; if (!vis[to]) { mq.push(to); vis[to] = 1; } } } } } int main(void) { int t; scanf("%d", &t); while (t--) { memset(head, -1, sizeof(head)); cnt = 0; scanf("%d", &n); int a, b, c; for (int i = 1; i <= n; i++) { scanf("%d", &b); addedge(0, i, -b); addedge(i, n + 1, b); } for (int i = 1; i <= n - 1; i++) { scanf("%d%d%d", &a, &b, &c); addedge(a, b, -c); addedge(b, a, -c); } memset(vis, 0, sizeof(vis)); for (int i = 0; i <= n + 1; i++) d[i] = -INF; spfa(0, n + 1); printf("%d\n", d[n + 1]); } return 0; }
HDU 6201【最長路+SPFA轉化為流問題求解***】