码迷,mamicode.com
首页 > 其他好文 > 详细

树形DP(2)

时间:2020-05-31 00:58:12      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:scanf   play   return   --   show   targe   pac   onclick   names   

一、P2656 采蘑菇

技术图片
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
#define maxn 80010
#define maxm 300010
struct Edge{
    int u,v,w,next;
    double k;
}edge[maxm];

int head[maxn],instack[maxn],stack[maxn],Belong[maxn];
int DFN[maxn],LOW[maxn],n,m,ant,Index,top,Bcnt;
int point[maxn],S,ans[maxn];

void adde(int u,int v,int w,double k){
    edge[ant].u=u,edge[ant].v=v;
    edge[ant].w=w,edge[ant].k=k;
    edge[ant].next=head[u],head[u]=ant++;
}

void tarjan(int u){
    DFN[u]=LOW[u]=++Index;
    instack[u]=true;
    stack[++top]=u;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        if(!DFN[v]){
            tarjan(v);
            if(LOW[v]<LOW[u])    LOW[u]=LOW[v];
        }
        else{
            if(instack[v]&&DFN[v]<LOW[u])    LOW[u]=DFN[v];
        }
    }
    if(DFN[u]==LOW[u]){
        Bcnt++;
        int j;
        do{
            j=stack[top--];
            instack[j]=false;
            Belong[j]=Bcnt;
        }
        while(j!=u);
    }
}

void solve(){
    top=Bcnt=Index=0;
    for(int i=1;i<=n;i++){
        if(!DFN[i])
            tarjan(i);
    }
}

void dfs(int p){
    ans[p]+=point[p];
    int t=0;
    for(int i=head[p];i!=-1;i=edge[i].next){
        int v=edge[i].v,w=edge[i].w;
        if(!ans[v])    dfs(v);
        t=max(t,ans[v]+w);    
    }
    ans[p]+=t;
}

int main(){
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        double k;
        scanf("%d%d%d%lf",&u,&v,&w,&k);
        adde(u,v,w,k);
    }
    scanf("%d",&S);
    solve();
    memset(head,-1,sizeof(head));
    for(int i=0;i<m;i++){
        int u=edge[i].u,v=edge[i].v;
        int w=edge[i].w;
        double k=edge[i].k;
        if(Belong[u]!=Belong[v]){
            
            adde(Belong[u],Belong[v],w,k);
        }else{
            while(w){
                point[Belong[u]]+=w;
                w=floor(w*k);
            }
        }
    }
    dfs(Belong[S]);
    printf("%d\n",ans[Belong[S]]);
    return 0;
}
View Code

缩点模板题,dfs一开始还写错了。

 

二、P1040 加分二叉树

技术图片
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
#define maxn 35

long long w[maxn],n,dp[maxn][maxn],root[maxn][maxn];

void myprint(int l,int r){
    if(l>r)    return;
    printf("%d ",root[l][r]);
    myprint(l,root[l][r]-1);
    myprint(root[l][r]+1,r);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)    scanf("%lld",&w[i]);
    for(int i=0;i<=n;i++){
        dp[i+1][i]=1;
        root[i][i]=i;
        dp[i][i]=w[i];
    }    
    for(int len=2;len<=n;len++){
        for(int i=1;i<n;i++){
            int j=i+len-1;
            for(int k=i;k<=j;k++){
                if(dp[i][j]<dp[i][k-1]*dp[k+1][j]+w[k]){
                    dp[i][j]=dp[i][k-1]*dp[k+1][j]+w[k];
                    root[i][j]=k;
                }
            }
        }
    }
    printf("%lld\n",dp[1][n]);
    myprint(1,n);
    return 0;
}
View Code

如果现在给出一个中序遍历的序列,并且给出你所有子树根节点 ,123456789(8是整个树的根,4是子树[1,6]的根(用区间表示子树),2是树[1,6]的子树[1,3]的根,而5是树[1,6]的子树[5,6]的根)。

root数组看的题解,有点妙!

树形DP(2)

标签:scanf   play   return   --   show   targe   pac   onclick   names   

原文地址:https://www.cnblogs.com/zx1473619689/p/12995606.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!