题意:有n个点,n-1条边的无向图,已知每个点书的售价,以及在边上行走的路费,问任选两个点作为起点和终点,能获得的最大利益是多少。
分析:
1、从某个结点出发,首先需要在该结点a花费price[a]买书,然后再在边上行走,到达目的地后,在目的地b获得price[b]。
2、因此可以建立两个虚拟结点,
虚拟结点1连向n个点,边权分别为-price[i],表示以i为起点,需花费price[i]买书。
n个点连向虚拟结点2,边权分别为price[i],表示以i为终点,通过卖书可得price[i]。
3、spfa求最长路即可得最大利益。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const LL MOD = 998244353; const double pi = acos(-1.0); const int MAXN = 100000 + 10; const int MAXT = 10000 + 10; using namespace std; int n; struct Edge{ int v, cost; Edge(int vv = 0, int c = 0):v(vv), cost(c){} }; vector<Edge> E[MAXN]; void addEdge(int u, int v, int w){ E[u].push_back(Edge(v, w)); } bool vis[MAXN]; int cnt[MAXN], dist[MAXN]; bool SPFA(int start){ memset(vis, false, sizeof vis); memset(cnt, 0, sizeof cnt); for(int i = 0; i < MAXN; ++i) dist[i] = -INT_INF; queue<int> q; while(!q.empty()) q.pop(); q.push(start); dist[start] = 0; vis[start] = true; cnt[start] = 1; while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; for(int i = 0; i < E[u].size(); ++i){ int v = E[u][i].v; if(dist[v] < dist[u] + E[u][i].cost){ dist[v] = dist[u] + E[u][i].cost; if(!vis[v]){ vis[v] = true; q.push(v); if(++cnt[v] > n) return false; } } } } return true; } int price[MAXN]; int main(){ int T; scanf("%d", &T); while(T--){ for(int i = 0; i < MAXN; ++i) E[i].clear(); scanf("%d", &n); for(int i = 1; i <= n; ++i){ scanf("%d", &price[i]); } int x, y, z; for(int i = 0; i < n - 1; ++i){ scanf("%d%d%d", &x, &y, &z); addEdge(x, y, -z); addEdge(y, x, -z); } for(int i = 1; i <= n; ++i){ addEdge(0, i, -price[i]); addEdge(i, n + 1, price[i]); } SPFA(0); printf("%d\n", dist[n + 1]); } return 0; }
时间: 2024-10-29 19:09:40