zoukankan      html  css  js  c++  java
  • Luogu_P2607 [ZJOI2008]骑士 P1453 城市环路 基环树+树形DP

    Luogu_P2607 [ZJOI2008]骑士 P1453 城市环路

    基环树+树形DP


    2607
    1453
    题目大意都是一样的,只要相连就不能同时取
    最大化权值
    但是有环
    那么就在搜到环之后记录(s)(t)表示环的两边
    两次树形DP
    第一次强制不取(s)
    第二次可取(s)
    找出两个的最优解


    P2607

    单向边而且是森林,就跳(fa[])
    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int maxn=1000010;
    int n,val[maxn],f[maxn][2],head[maxn],tot,vis[maxn],fa[maxn],rt,ans;
    struct node{
        int nxt,to;
        #define nxt(x) e[x].nxt
        #define to(x) e[x].to
    }e[maxn];
    inline void add(int from,int to){
        to(++tot)=to;nxt(tot)=head[from];head[from]=tot;
    }
    void dp(int x){
        vis[x]=1;
        f[x][0]=0;f[x][1]=val[x];
        for(int i=head[x];i;i=nxt(i)){
            int y=to(i);
            if(y==rt){
                f[y][1]=-maxn;
            }else{
                dp(y);f[x][0]+=max(f[y][1],f[y][0]);f[x][1]+=f[y][0];
            }
        }
    }
    void fdc(int x){
        vis[x]=1;
        rt=x;
        while(!vis[fa[rt]]){
            rt=fa[rt];vis[rt]=1;
        }
        dp(rt);
        int now=f[rt][0];
        dp(rt=fa[rt]);
        ans+=max(now,f[rt][0]);
    }
    signed main(){
        scanf("%lld",&n);
        for(int x,y,i=1;i<=n;i++){
            scanf("%lld%lld",&x,&y);add(y,i);f[i][1]=x;fa[i]=y;val[i]=x;
        }
        for(int i=1;i<=n;i++) if(!vis[i]) fdc(i);
        printf("%lld
    ",ans);
        return 0;
    }
    

    P1453

    无向边且是一颗
    就可以用并查集方便的求s和t

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100010;
    int n,p[maxn],fa[maxn],f[maxn][2],ans;
    struct node{
        int nxt,to;
        #define nxt(x) e[x].nxt
        #define to(x) e[x].to
    }e[maxn<<1];
    int head[maxn],tot,s,t;
    double k;
    inline int find(int x){return fa[x]==x ? fa[x] : fa[x]=find(fa[x]);}
    inline void add(int from,int to){
        to(++tot)=to;nxt(tot)=head[from];head[from]=tot;
    }
    void dfs(int x,int fa){
        f[x][0]=0;f[x][1]=p[x];
        for(int i=head[x];i;i=nxt(i)){
            int y=to(i);
            if(y==fa) continue;
            dfs(y,x);
            f[x][0]+=max(f[y][1],f[y][0]);f[x][1]+=f[y][0];
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) fa[i]=i,scanf("%d",&p[i]);
        for(int x,y,i=1;i<=n;i++){
            scanf("%d%d",&x,&y);x++;y++;
            if(find(x)==find(y)){s=x,t=y;continue;}
            add(x,y);add(y,x);fa[find(x)]=find(y);
        }
        scanf("%lf",&k);
        dfs(s,0);ans=max(ans,f[s][0]);
        dfs(t,0);ans=max(ans,f[t][0]);
        printf("%.1lf
    ",(double)ans*k);
        return 0;
    }
    
  • 相关阅读:
    Java面试
    md5加密
    CSS3画苹果手机
    CSS3的表格布局 文字居中 圆角
    CSS3的新特性 行内盒子before和after
    DIV CSS Sprites精灵 CSS图像拼合 CSS背景贴图定位教程案例
    DAY30
    DedeCMS织梦修改数据库密码和数据库连接失败解决方法
    学习计划
    【原】雅虎前端优化的35条军规
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11640538.html
Copyright © 2011-2022 走看看