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

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9/3 树形dp+树的直径+最长路径 +st表相关的知识,希望对你有一定的参考价值。

P1352 没有上司的舞会

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

#include<bits/stdc++.h>
#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;



树的直径 Computer

树形dp

//#include<bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#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;



最长路径

Roads in the North POJ - 2631

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#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;



Strategic game

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

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
//#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;



P3088 [USACO13NOV]Crowded Cows S

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

#include<bits/stdc++.h>
#define Computer(HDU2196)——树形dp的那些事

树的直径

树形dp (二叉树中的最大路径最长距离)

bzoj1907树的路径覆盖 树形dp

bzoj 1907: 树的路径覆盖贪心+树形dp

bzoj1907: 树的路径覆盖(树形DP)