HDU

题意:有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
", dist[n + 1]);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/7528380.html