• 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;
    }
  • 相关阅读:
    LINUX 蓝牙耳机的配置方法
    Android_0.9 蓝牙栈bluez使用方法
    G1 安装 Linux Debian system
    Linux下基于Bluez4.x的蓝牙耳机配置
    【转】ARM平台上蓝牙协议栈Bluez的移植使用和配置
    Debian下编译安装驱动模块
    nginx多虚拟主机配置 Leone
    nginx以unixdomainsocket方式连接fastcgi(php) Leone
    Nginx多站点虚拟主机实现单独启动停止phpfpm、单独控制权限设置 Leone
    开启Apache2.2的deflate和expires模块来提升网页浏览速度 Leone
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9815381.html
Copyright © 2020-2023  润新知