HDU

Kelukin is a businessman. Every day, he travels around cities to do some business. On August 17th, in memory of a great man, citizens will read a book named "the Man Who Changed China". Of course, Kelukin wouldn't miss this chance to make money, but he doesn't have this book. So he has to choose two city to buy and sell.
As we know, the price of this book was different in each city. It is i  ai yuayuan in i t city. Kelukin will take taxi, whose price is 1 yuayuan per km and this fare cannot be ignored.
There are nn−1 roads connecting n cities. Kelukin can choose any city to start his travel. He want to know the maximum money he can get.

InputThe first line contains an integer T (1T10 1≤T≤10 ) , the number of test cases.
For each test case:
first line contains an integer n (2n100000 2≤n≤100000 ) means the number of cities;
second line contains n numbers, the i tth number means the prices in i tth city; (1Price10000(1≤Price≤10000)
then follows nn−1 lines, each contains three numbers x , y and z which means there exists a road between x and y , the distance is z kkm (1z1000(1≤z≤1000) .
OutputFor each test case, output a single number in a line: the maximum money he can get.
Sample Input

1  
4  
10 40 15 30  
1 2 30
1 3 2
3 4 10

Sample Output

8

题意:现在有一棵树,每个节点有自己的价格,边之间有运费,问最大差价是多少。

思路:可以树DP。这里用的最长路,没想到啊。   每个点与源点连一个正价,与汇点连一个负价。然后跑最长路,就可以得到最大收益。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int inf=1e9+7;
const int maxn=400010;
int S,T,a[maxn],Laxt[maxn],Next[maxn],To[maxn],Len[maxn],dis[maxn],in[maxn],cnt;
void add(int u,int v,int w){
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
void read(int &x){
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
}
void SPFA()
{
    rep(i,0,T) dis[i]=-inf,in[i]=0;
    dis[S]=0; queue<int>q;
    q.push(S); in[S]=1;
    while(!q.empty()){
        int u=q.front(); q.pop();
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i]; if(dis[u]+Len[i]>dis[v]) {
                dis[v]=dis[u]+Len[i];
                if(!in[v]) in[v]=1,q.push(v);
            }
        }in[u]=0;
    }
}
int main()
{
    int Case,N,u,v,w;
    scanf("%d",&Case);
    while(Case--){
        read(N); T=N+1;
        rep(i,1,N) read(a[i]);
        rep(i,0,T) Laxt[i]=0; cnt=0;
        rep(i,1,N-1){
            read(u); read(v); read(w);
            add(u,v,-w); add(v,u,-w);
        }
        rep(i,1,N) add(S,i,-a[i]);
        rep(i,1,N) add(i,T,a[i]);
        SPFA();
        printf("%d
",dis[T]);
    }
    return 0;
}

数据比较奇葩,普通的SPFA效率比优先队列的高。。。

#include<bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int inf=1e9+7;
const int maxn=400010;
int S,T,a[maxn],Laxt[maxn],Next[maxn],To[maxn],Len[maxn],dis[maxn],cnt;
void add(int u,int v,int w){
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
void SPFA()
{
    rep(i,0,T) dis[i]=-inf; dis[S]=0;
    priority_queue<pii>q;
    q.push(mp(-0,S));
    while(!q.empty()){
        int u=q.top().second; q.pop();
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i]; if(dis[u]+Len[i]>dis[v]) {
                dis[v]=dis[u]+Len[i];
                q.push(mp(-dis[v],v));
            }
        }
    }
}
int main()
{
    int C,N,u,v,w;
    scanf("%d",&C);
    while(C--){
        scanf("%d",&N); T=N+1;
        rep(i,1,N) scanf("%d",&a[i]);
        rep(i,0,T) Laxt[i]=0; cnt=0;
        rep(i,1,N-1){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,-w); add(v,u,-w);
        }
        rep(i,1,N) add(S,i,a[i]);
        rep(i,1,N) add(i,T,-a[i]);
        SPFA();
        printf("%d
",dis[T]);
    }
    return 0;
}
View Code

树DP,Mn表示经过这个点到子树里买的最小值,Mx表示经过这个点到子树里卖的最大值,每次上传时由于多经过一条边,减去边权更新即可:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
int Mx[maxn],Mn[maxn];
int Laxt[maxn],Next[maxn],To[maxn],Len[maxn],cnt,ans;
void add(int u,int v,int w){
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
void dfs(int u,int fa){
    for(int i=Laxt[u];i;i=Next[i]){
        int v=To[i];
        if(v!=fa) {
           dfs(v,u);
           Mn[u]=min(Mn[v]+Len[i],Mn[u]);
           Mx[u]=max(Mx[v]-Len[i],Mx[u]);
        }
    }
    ans=max(Mx[u]-Mn[u],ans);
}
int main()
{
    int T,N,u,v,w;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        rep(i,1,N) Laxt[i]=0;
        cnt=0; ans=0;
        rep(i,1,N) scanf("%d",&Mn[i]),Mx[i]=Mn[i];
        rep(i,1,N-1){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }
        dfs(1,0);
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/9815381.html