• 9/3 树形dp+树的直径+最长路径 +st表


    P1352 没有上司的舞会

    设计状态:
    f[u][0]表示u不去舞会,其子树的累加和的最大值
    f[u][1]表示u去舞会,其直系下属不去舞会,但已下属为根节点的子树的快乐指数需要累加

    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=2e6+7;
    const int inf=1e18;
    const int mod=19980829;
    int n,a[N],din[N],f[N][2];
    vector<int>e[N];
    void dfs(int u,int pre)
    {
        f[u][1]=a[u];
        for(int v:e[u])
        {
            if(v==pre) continue;
            dfs(v,u);
            f[u][1]+=f[v][0];
            f[u][0]+=max(f[v][1],f[v][0]);
        }
    }
    void solve()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<n;i++)
        {
            int u,v;cin>>u>>v;
            e[u].push_back(v);
            e[v].push_back(u);
            din[u]++;
        }
        int g;
        for(int i=1;i<=n;i++)
            if(!din[i]) g=i;
        dfs(g,0);
        cout<<max(f[g][0],f[g][1])<<endl;
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    树的直径 Computer

    树形dp

    //#include
    #include 
    #include 
    #include 
    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=2e6+7;
    const int inf=1e18;
    const int mod=19980829;
    int n,cnt,head[N],dp[N][3],p[N];
    struct node
    {
        int to,nxt,w;
    }e[N];
    void add(int from,int to,int w)
    {
        e[++cnt].to=to;
        e[cnt].w=w;
        e[cnt].nxt=head[from];
        head[from]=cnt;
    }
    void dfs1(int u,int pre)
    {
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==pre) continue;
            dfs1(v,u);
            if(dp[v][0]+e[i].w>dp[u][0])
            {
                dp[u][1]=dp[u][0];
                dp[u][0]=dp[v][0]+e[i].w;
                p[u]=v;
            }
            else if(dp[v][0]+e[i].w>dp[u][1])
                dp[u][1]=dp[v][0]+e[i].w;
        }
    }
    void dfs2(int u,int pre)
    {
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==pre) continue;
            if(v==p[u])
                dp[v][2]=e[i].w+max(dp[u][1],dp[u][2]);
            else
                dp[v][2]=e[i].w+max(dp[u][0],dp[u][2]);
            dfs2(v,u);
        }
    }
    void solve()
    {
        while(cin>>n)
        {
            cnt=0;
            for(int i=0;i<=n;i++)
                head[i]=dp[i][0]=dp[i][1]=dp[i][2]=p[i]=0;
            for(int i=2;i<=n;i++)
            {
                int v,w;cin>>v>>w;
                add(i,v,w),add(v,i,w);
            }
            dfs1(1,0);
            dfs2(1,0);
            for(int i=1;i<=n;i++)
                cout<<max(dp[i][0],dp[i][2])<<endl;
        }
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    最长路径

    Roads in the North POJ - 2631

    #include 
    #include 
    #include 
    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=2e6+7;
    const int inf=1e18;
    const int mod=19980829;
    int ans,cnt,head[N],d[N];
    bool vis[N];
    struct node
    {
        int to,nxt,w;
    }e[N];
    void add(int from,int to,int w)
    {
        e[++cnt].to=to;
        e[cnt].w=w;
        e[cnt].nxt=head[from];
        head[from]=cnt;
    }
    int dfs1(int u)
    {
        d[u]=0;
        vis[u]=1;
        int d1=0,d2=0;
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(vis[v]) continue;
            dfs1(v);
            if(d[v]+e[i].w>=d1)
                d2=d1,d1=d[v]+e[i].w;
            else if(d[v]+e[i].w>d2)
                d2=d[v]+e[i].w;
        }
        d[u]=d1;
        return d1+d2;
    }
    
    void solve()
    {
        int u,v,w;
        while(scanf("%d%d%d", &u, &v, &w) == 3)
        {
            add(u,v,w),add(v,u,w);
        }
        ans=dfs1(1);
        printf("%d\n", ans);
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    Strategic game

    思路是正解,但总是报运行错误,找了半个多小时,索性不找了,可能是码分问题,也不常在这个oj上做题。
    问题找到了,在poj上用define int long long要小心!!!
    该问题的本质是求解最少边覆盖。若该点放置士兵,则子结点应选择代价较少的士兵数;若改点不放置士兵,则其子节点必须放置士兵。

    #include 
    #include 
    #include 
    #include
    //#define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=3005;
    const int inf=1e18;
    const int mod=19980829;
    int n,cnt,head[N],dp[N][2],din[N];
    bool vis[N];
    struct node
    {
        int to,nxt;
    }e[N];
    void add(int from,int to)
    {
        e[++cnt].to=to;
        //e[cnt].w=w;
        e[cnt].nxt=head[from];
        head[from]=cnt;
    }
    void dfs(int u,int pre)
    {
        vis[u]=1;
        dp[u][1]=1;
        for(int i=head[u];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==pre||vis[v]) continue;
            dfs(v,u);
            dp[u][1]+=min(dp[v][0],dp[v][1]);
            dp[u][0]+=dp[v][1];
        }
    
    }
    
    void solve()
    {
        while(~scanf("%d",&n))
        {
            cnt=0;
            for(int i=0;i<=n;i++)
                head[i]=-1,dp[i][0]=dp[i][1]=vis[i]=0;
            for(int i=1;i<=n;i++)
            {
                int u,v,d;scanf("%d:(%d)",&u,&d);
                for(int j=1;j<=d;j++)
                {
                    cin>>v;
                    add(u,v);add(v,u);
                }
            }
            dfs(0,-1);
            printf("%d\n",min(dp[0][0],dp[0][1]));
        }
    
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    P3088 [USACO13NOV]Crowded Cows S

    小工具:可用lowerbound处理每个点所在左右边界的关系

    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=5e5+5;;
    const int inf=1e18;
    const int mod=19980829;
    int n,d,g,a[N];
    struct node
    {
        int x,h;
        bool operator <(const node &a){
            return x<a.x;
        }
    }e[N];
    struct n1
    {
        int l,r;
    }c[N];
    //ST表
    int lg[N];  //记录log2N的整数值
    int st[N][30];  //以i为左端点长度为2的j次方的序列所求最值
    void ST(int n)
    {
        lg[1]=0;
        for(int i=2;i<=n;i++)
            lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
        for(int i=1;i<=n;i++)
            st[i][0]=e[i].h;
        for(int j=1;(1<<j)<=n;j++)
        {
            for(int i=1;i+(1<<j)-1<=n;i++)
                st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
        }
    }
    int sch(int l,int r)
    {
        if(l>r)
            return 0;
        int k=lg[r-l+1];
        return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    
    void solve()
    {
        cin>>n>>d;
        for(int i=1;i<=n;i++)
            cin>>e[i].x>>e[i].h;
        sort(e+1,e+n+1);
        for(int i=1;i<=n;i++)
        {
            int d1=e[i].x-d,d2=e[i].x+d;
            int pos1=lower_bound(e+1,e+n+1,node{d1,e[i].h})-e;
            int pos2=lower_bound(e+1,e+n+1,node{d2,e[i].h})-e;
            if(e[pos2].x>d2) pos2--;
            if(pos2>n) pos2--;
            //cout<
            c[++g].l=pos1,c[g].r=pos2;
        }
        ST(n);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int mx1=sch(c[i].l,i),mx2=sch(i,c[i].r);
            //cout<
            if(mx1>=e[i].h*2&&mx2>=e[i].h*2)
                ans++;
        }
        cout<<ans<<endl;
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
  • 相关阅读:
    ES6语法新特性(上)
    .NET 发布,部署和运行应用程序
    MTK LCM调试总结
    matlab这样子写为什么运行不出正确的结果嘞
    Windows列出系统所有补丁(wmic)
    1 快速了解Paimon数据湖核心原理及架构
    【附源码】Python计算机毕业设计社区住户信息管理系统
    性能测试常见问题总结
    软件设计师--数据结构考点细节总结
    Linux命令解压多个tar.gz包
  • 原文地址:https://blog.csdn.net/weixin_51934288/article/details/126679583