zoukankan      html  css  js  c++  java
  • ural(Timus) 1463. Happiness to People!

    树DP

    题意:输入n和m,表示n个城市,m条无向边,下面一行n个数字,表示每个城市的权值,下面m行是每条边的信息,u,v,w,顶点和边权。问你从一个城市出发,走出一条路线,使得权值和最大,权值和包括这条路线上城市的权值和边的权值和。

    题中有一句话出卖了它是个树DP:It turned out that if Petrovich can fly (using one or several flights) from town i to town j, then there is exactly one way to do this.

    从一个顶点去另一个顶点如果连通的话只有一条路径,说明这个无向图其实是个无根树,所以又变成了经典问题,在无根树中找两点使它们的路径最长,不过这里要加上点的权值而已,是一样的,另外一个点是要记录路径的,输出路径中经过了多少个点,并且沿路径输出每一个点,如果有多条路径任意一条即可

    DP思路不说了,可以找前面的题解里面有详细的讲解,说说输出路径。我是分两部分来输出路径的,根到叶子的最大值为一个部分,到叶子的次大值是另一个部分,根据路径输出的要求,前面部分要递归输出,或者可以用一个栈保存,比较懒就用了stl的stack来保存路径,后面的部分不用递归,直接迭代下去,但是为了统计点的个数所以先保存,用了stl的queue来保存路径

    整个题目其实不难,注意细节即可

    #include <cstdio>
    #include <cstring>
    #include <utility>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    using namespace std;
    #define N 50010
    
    typedef long long ll;
    typedef pair<ll,ll> pll;
    bool vis[N];
    vector<pll>a[N];
    stack<int>s;
    queue<int>q;
    ll val[N];
    ll dp[N][2];
    ll ans;
    int n,m,root;
    int p[N][2];
    
    void input()
    {
        for(int i=0; i<=n; i++) 
            a[i].clear();
        for(int i=1; i<=n; i++) 
            scanf("%lld",&val[i]);
        for(int i=0; i<m; i++)
        {
            int u,v,w;
            pll tmp;
            scanf("%d%d%d",&u,&v,&w);
            tmp.first=v; tmp.second=w; a[u].push_back(tmp);
            tmp.first=u; tmp.second=w; a[v].push_back(tmp);
        }
    }
    
    void dfs(int rt)
    {
        vis[rt]=true;
        dp[rt][1]=dp[rt][0]=0; 
        p[rt][1]=p[rt][0]=-1;
    
        int size=a[rt].size();
        for(int i=0; i<size; i++)
        {
            pll tmp = a[rt][i];
            int v = tmp.first;
            int w = tmp.second;
            if(!vis[v])
            {
                dfs(v);
                if(dp[v][1] + w >= dp[rt][1])
                {
                    dp[rt][0] = dp[rt][1];
                    p[rt][0] = p[rt][1];
                    dp[rt][1] = dp[v][1]+w;
                    p[rt][1] = v;
                }
                else if(dp[v][1] + w > dp[rt][0])
                {
                    dp[rt][0] = dp[v][1] + w;
                    p[rt][0] = v;
                }
            }
        }
    
        dp[rt][1] += val[rt];
        dp[rt][0] += val[rt];
        if( dp[rt][1]+dp[rt][0]-val[rt] > ans)
        {
            root=rt;
            ans = dp[rt][1]+dp[rt][0]-val[rt];
        }
    }
    
    int Path1(int rt)
    {
        int cc=1;
        int u;
        while(!s.empty()) s.pop();
        s.push(rt);
        for(u=p[rt][1]; u!=-1; u=p[u][1])
        {
            s.push(u);
            cc++;
        }
        return cc;
    }
    
    int Path2(int rt)
    {
        int cc=0;
        int u;
        while(!q.empty()) q.pop();
        for(u=p[rt][0]; u!=-1; u=p[u][1])
        {
            q.push(u);
            cc++;
        }
        return cc;
    }
    
    void solve()
    {
        memset(vis,false,sizeof(vis));
        memset(p,-1,sizeof(p));
        ans=-1;   
        /*
        初始化为
        ans=0;
        root=1; //不要初始化为0
        */
        for(int i=1; i<=n; i++)
            if(!vis[i])
                dfs(i);
        printf("%lld\n",ans);
    
        int c1=Path1(root);
        int c2=Path2(root);
        printf("%d\n",c1+c2);
    
        while(!s.empty())
        {
            int t=s.top();
            s.pop();
            if(t!=root) printf("%d ",t);
            else        printf("%d",t);
        }
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            printf(" %d",t);
        }
        printf("\n");
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            input();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    设计模式学习总结系列应用实例
    【研究课题】高校特殊学生的发现及培养机制研究
    Linux下Oracle11G RAC报错:在安装oracle软件时报file not found一例
    python pro practice
    openstack python sdk list tenants get token get servers
    openstack api
    python
    git for windows
    openstack api users list get token get servers
    linux 流量监控
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3013443.html
Copyright © 2011-2022 走看看