• 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;
    }
  • 相关阅读:
    字节跳动2020年九月笔试题-爬楼梯(不能连续爬两个两步)
    c/c++经典面试题-part1
    C++单例模式之一见钟情
    多线程同步的四种方式(史上最详细+用例)
    c++多态之动态绑定
    Redis从入门到入坑
    编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串 是由同一字符组成的。
    面试之进制转换函数
    c++编程题之空调遥控器
    static 和 const关键字的作用
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9815381.html
Copyright © 2020-2023  润新知