• 树形DP


    去学习了一下树形DP然后发现自己什么都不会!!!!!!

    GGGGGGG。

    首先是广为人知的一道

    没有上司的舞会

    emm没啥可说的,很久以前写的一道题

    对于每一个节点有两种状态,选上司或选下属,分别做就好了。

    因此

    dp[i][0]=sum(max(dp[son][1],dp[son][0]));//显然,你不去,那下属就可以想去就去。

    dp[i][1]=sum(dp[son][0])+happy[i];//显然你去了那下属就一定不能去。

    #include<bits/stdc++.h>
    using namespace std;
    vector<int>son[10010];
    int f[10010][2],v[10010],h[10010],n;
    void dp(int x){
        f[x][0]=0;
        f[x][1]=h[x];
        for(int i=0;i<son[x].size();i++){
          int y=son[x][i];
          dp(y);
          f[x][0]+=max(f[y][0],f[y][1]);
          f[x][1]+=f[y][0];     
        }
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++)cin>>h[i];
        for(int i=1;i<n;i++){
            int x,y;
            cin>>x>>y;
            v[x]=1;
            son[y].push_back(x);
            }
        int root;
        for(int i=1;i<=n;i++){
            if(!v[i]){
                root=i;
                break;
            }
        }
        dp(root);
        cout<<max(f[root][0],f[root][1])<<endl;
    }

    然后是

    最大子树和

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5211314; 
    struct node{
        int next,to;
    } e[N];
    int head[N],cnt,n,dp[N],a[N],ans,val[N];
    void add(int u,int v){
        e[++cnt].next=head[u];
        e[cnt].to=v;
        head[u]=cnt; 
    } 
    void dfs(int u,int fa){
        dp[u]=a[u];
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v!=fa){
               dfs(v,u);
               dp[u]+=max(0,dp[v]); 
            } 
        } 
        ans=max(ans,dp[u]); 
    } 
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]); 
        } 
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u); 
        } 
        dfs(1,0);
        printf("%d
    ",ans);
        return 0; 
    } 

      

    选课

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5211314;
    int n,m;
    struct node{
        int next,to;
    } e[N];
    int head[N],dp[5041][5041],cnt,a[N],val[N];
    void add(int u,int v){
        e[++cnt].next=head[u];
        e[cnt].to=v;
        head[u]=cnt; 
    } 
    void dfs(int u){
        dp[u][1]=val[u]; 
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            dfs(v);
            for(int j=m;j>=1;j--){
                for(int k=j-1;k>=1;k--){
                    dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]); 
                } 
            } 
        } 
    } 
    int main(){
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i],&val[i]); 
            add(a[i],i); 
        } 
            m++;
        dfs(0);
        printf("%d
    ",dp[0][m]); 
        return 0;
    } 

      

    [USACO12FEB]附近的牛Nearby Cows

    换根法好题

    #include<bits/stdc++.h>
    using namespace std;
    struct node{
        int to,next;
    }e[210001];
    int head[100001],len;
    int f[100001][21],sons[100001];//状态,孩子数
    int a,b,n,k;
    void build(){
        e[++len].to=b;
        e[len].next=head[a];
        head[a]=len;
        e[++len].to=a;
        e[len].next=head[b];
        head[b]=len;
        sons[a]++;sons[b]++;
    }
    int main(){
        int i,j,s;
        scanf("%d%d",&n,&k);
        for(i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            build();
        }
        for(i=1;i<=n;i++)cin>>f[i][0];
        for(j=1;j<=k;j++)
            for(i=1;i<=n;i++){
                for(s=head[i];s;s=e[s].next)
                    f[i][j]+=f[e[s].to][j-1];
                if(j>1)f[i][j]-=(sons[i]-1)*f[i][j-2];
                else f[i][1]+=f[i][0]; 
            }
        for(i=1;i<=n;i++)
            printf("%d
    ",f[i][k]); 
        return 0;
    }

      

    还有一道也是换根法好题。

    【POJ3585】Accumulation Degree

    我才不会说我被卡了好久好久。。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define zero(x) memset(x,0,sizeof(x))
    using namespace std;
    const int N=500001;
    struct node{
        int next,to;
    } e[N*2];
    inline int read() {
        int a = 0;
        char ch = getchar();
        while (!(ch >= '0' && ch <= '9')) ch = getchar();
        while (ch >= '0' && ch <= '9') {
            a = a * 10 + (ch - '0');
            ch = getchar();
        }
        return a;
    }
    bool vis[N];
    int n,T;
    int head[N],in[N],val[N],cnt,dp[N],d[N];
    void add(int u,int v,int z){
        e[++cnt].next=head[u];
        val[cnt]=z; 
        e[cnt].to=v;
        head[u]=cnt; 
    } 
    void dps(int x){
        vis[x]=1;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v])continue;
            dps(v);
            if(in[v]==1){
               d[x]+=val[i]; 
            } 
            else d[x]+=min(d[v],val[i]); 
        } 
    } 
    void dfs(int x){
        vis[x]=1;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v])continue;
            if(in[x]==1)dp[v]=d[v]+val[i];
            else dp[v]=d[v]+min(dp[x]-min(d[v],val[i]),val[i]);
            dfs(v); 
        } 
    } 
    int main(){
        int t=read();
        while(t--){
            zero(vis),zero(val),zero(dp),zero(d);zero(in); 
            zero(e),zero(head); 
            scanf("%d",&n);cnt=0;
            for(int i=1;i<n;i++){
                int x=read(),y=read(),z=read();
                in[x]++,in[y]++; 
                add(x,y,z),add(y,x,z); 
            } 
            dps(1);memset(vis,0,sizeof(vis));
            dp[1]=d[1];
            dfs(1);int ans=0;
            for(int i=1;i<=n;i++) ans=max(ans,dp[i]);//求最大值
            printf("%d
    ",ans);//输出
        } 
    } 

    暂时完结以后有新的再填吧。

    作者:wilxx
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    typeof 和 Object.prototype.toString 的区别
    获取地理信息的JavaScript 库 -- YQL Geo
    关于html5手机
    我看过的书的示例网站
    解决跨浏览器问题网站收集
    【docker】docker初试与填坑
    sunJCE or ibmJce,was服务器下使用des的注意点
    cxf-webservice-在was6服务器上运行
    微星b85(b85i b85-gaming) 系列dsdt
    IE10的bug?disabled button如何触发事件
  • 原文地址:https://www.cnblogs.com/wilxx/p/11770432.html
Copyright © 2020-2023  润新知