• csu 2014 summer training day 3 简单树形dp


    FZU 2157

    题意:树上的节点可以打上0或1的标记,树的权值由两部分呢组成,点权和边权,有00、01、10、11四种组合的边权,

    问最小权值和。以1节点为树根

    分析:dp[x][0]表示x标记0后的最小的权值,dp[x][1]同理

    那么每次可以计算dp[x][0],dp[x][1];

    例如dp[x][1]=min(dp[son][0]+lab[0][1]+val[1],dp[son][1]+bal[1][1]+val[1]);

    具体看代码。

    用bfs写的分层,深搜代码更简洁

     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 #include <vector>
     5 #include <map>
     6 #include <string>
     7 #include <queue>
     8 #define LL long long
     9 #define maxn 201000
    10 using namespace std;
    11 //map存储标号
    12 //边读边记录边的关系
    13 //bfs分层记录每层节点
    14 //从底层向上层dp
    15 int la[maxn][2];
    16 int bel[maxn][2][2];
    17 vector<int> G[maxn];
    18 vector<int> Ceil[maxn];
    19 int n,cnum;//点数,分层数
    20 void init(){
    21     for(int i=0;i<maxn;i++) G[i].clear();
    22     for(int i=0;i<maxn;i++) Ceil[i].clear();
    23     cnum=0;
    24     return ;
    25 }
    26 typedef pair<int,int>PAIR;
    27 bool vis[maxn];
    28 void Bfs(){
    29     queue<PAIR> Q ;
    30     Q.push(make_pair(1,1));
    31     memset(vis,0,sizeof(vis));
    32     vis[1]=true;
    33     while(!Q.empty()){
    34         PAIR New=Q.front();
    35         Q.pop();
    36         int u=New.first;
    37         int st=New.second;
    38         Ceil[st].push_back(u);
    39         cnum=max(cnum,st);
    40         for(int i=0;i<G[u].size();i++){
    41             int v=G[u][i];
    42             if (vis[v]) continue;
    43             Q.push(make_pair(v,st+1));
    44             vis[v]=true;
    45         }
    46     }
    47     return;
    48 }
    49 LL dp[maxn][2];//0表示不选择i节点,1表示选择i节点
    50 void solve(){
    51     memset(dp,0,sizeof(dp));
    52     for(int i=0;i<Ceil[cnum].size();i++){
    53         int u=Ceil[cnum][i];
    54         dp[u][0]=(LL)la[u][0];dp[u][1]=(LL)la[u][1];
    55     }
    56     for(int i=cnum-1;i>=1;i--){
    57         for(int j=0;j<Ceil[i].size();j++){
    58             int u=Ceil[i][j];
    59             for(int k=0;k<G[u].size();k++){
    60                 int v=G[u][k];
    61                 dp[u][0]+=min(dp[v][0]+bel[v][0][0],dp[v][1]+bel[v][0][1]);
    62                 dp[u][1]+=min(dp[v][0]+bel[v][1][0],dp[v][1]+bel[v][1][1]);
    63             }
    64             dp[u][1]+=(LL)la[u][1];
    65             dp[u][0]+=(LL)la[u][0];
    66 //            cout<<"u="<<u<<","<<"1:"<<dp[u][1]<<endl;
    67 //            cout<<"u="<<u<<","<<"0:"<<dp[u][0]<<endl;
    68         }
    69     }
    70     printf("%I64d
    ",min(dp[1][1],dp[1][0]));
    71     return ;
    72 }
    73 int t;
    74 int main(){
    75     scanf("%d",&t);
    76     while(t--){
    77         scanf("%d",&n);
    78         init();
    79         for(int i=1;i<=n;i++){
    80             scanf("%d",&la[i][0]);
    81         }
    82         for(int i=1;i<=n;i++){
    83             scanf("%d",&la[i][1]);
    84         }
    85         int u,v,a,b,c,d;
    86         for(int i=1;i<=n-1;i++){
    87             scanf("%d%d%d%d%d%d",&u,&v,&a,&b,&c,&d);
    88             bel[v][0][0]=a;
    89             bel[v][0][1]=b;
    90             bel[v][1][0]=c;
    91             bel[v][1][1]=d;
    92             G[u].push_back(v);
    93         }
    94         Bfs();//分层
    95         solve();
    96     }
    97     return 0;
    98 }
    View Code

    POJ 2342

    题意:给定一颗boss树,父亲节点和孩子节点不能同时出现,问最多能选出多少节点

    分析:dp[x][0]:x不出现,dp[x][1]:x出现

    dp[u][0]+=max(dp[v][1],dp[v][0]);
    dp[u][1]+=dp[v][0];
     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 #include <vector>
     5 #include <map>
     6 #include <string>
     7 #include <queue>
     8 #define LL long long
     9 #define maxn 201000
    10 using namespace std;
    11 //map存储标号
    12 //边读边记录边的关系
    13 //bfs分层记录每层节点
    14 //从底层向上层dp
    15 int la[maxn][2];
    16 int bel[maxn][2][2];
    17 vector<int> G[maxn];
    18 vector<int> Ceil[maxn];
    19 int n,cnum;//点数,分层数
    20 void init(){
    21     for(int i=0;i<maxn;i++) G[i].clear();
    22     for(int i=0;i<maxn;i++) Ceil[i].clear();
    23     cnum=0;
    24     return ;
    25 }
    26 typedef pair<int,int>PAIR;
    27 bool vis[maxn];
    28 void Bfs(){
    29     queue<PAIR> Q ;
    30     Q.push(make_pair(1,1));
    31     memset(vis,0,sizeof(vis));
    32     vis[1]=true;
    33     while(!Q.empty()){
    34         PAIR New=Q.front();
    35         Q.pop();
    36         int u=New.first;
    37         int st=New.second;
    38         Ceil[st].push_back(u);
    39         cnum=max(cnum,st);
    40         for(int i=0;i<G[u].size();i++){
    41             int v=G[u][i];
    42             if (vis[v]) continue;
    43             Q.push(make_pair(v,st+1));
    44             vis[v]=true;
    45         }
    46     }
    47     return;
    48 }
    49 LL dp[maxn][2];//0表示不选择i节点,1表示选择i节点
    50 void solve(){
    51     memset(dp,0,sizeof(dp));
    52     for(int i=0;i<Ceil[cnum].size();i++){
    53         int u=Ceil[cnum][i];
    54         dp[u][0]=(LL)la[u][0];dp[u][1]=(LL)la[u][1];
    55     }
    56     for(int i=cnum-1;i>=1;i--){
    57         for(int j=0;j<Ceil[i].size();j++){
    58             int u=Ceil[i][j];
    59             for(int k=0;k<G[u].size();k++){
    60                 int v=G[u][k];
    61                 dp[u][0]+=min(dp[v][0]+bel[v][0][0],dp[v][1]+bel[v][0][1]);
    62                 dp[u][1]+=min(dp[v][0]+bel[v][1][0],dp[v][1]+bel[v][1][1]);
    63             }
    64             dp[u][1]+=(LL)la[u][1];
    65             dp[u][0]+=(LL)la[u][0];
    66 //            cout<<"u="<<u<<","<<"1:"<<dp[u][1]<<endl;
    67 //            cout<<"u="<<u<<","<<"0:"<<dp[u][0]<<endl;
    68         }
    69     }
    70     printf("%I64d
    ",min(dp[1][1],dp[1][0]));
    71     return ;
    72 }
    73 int t;
    74 int main(){
    75     scanf("%d",&t);
    76     while(t--){
    77         scanf("%d",&n);
    78         init();
    79         for(int i=1;i<=n;i++){
    80             scanf("%d",&la[i][0]);
    81         }
    82         for(int i=1;i<=n;i++){
    83             scanf("%d",&la[i][1]);
    84         }
    85         int u,v,a,b,c,d;
    86         for(int i=1;i<=n-1;i++){
    87             scanf("%d%d%d%d%d%d",&u,&v,&a,&b,&c,&d);
    88             bel[v][0][0]=a;
    89             bel[v][0][1]=b;
    90             bel[v][1][0]=c;
    91             bel[v][1][1]=d;
    92             G[u].push_back(v);
    93         }
    94         Bfs();//分层
    95         solve();
    96     }
    97     return 0;
    98 }
    View Code

    HDU 2196

    题意:给定一棵树,分别求1..N分别作为树根时,最长的树枝长是多少?

    分析:两遍dfs,第一遍处理出(以1为根节点):

    int max1[maxn];//以1为根,i节点的最长路径
    int max2[maxn];//以1为根,i节点的次长路径,保证最长边的下一点不在这条路径上

    记录下相应的下一个节点的编号:

    int max1id[maxn];
    int max2id[maxn];

    第二遍处理出:转移节点后每个点作为根节点点的max1和max2,dfs搜索更新,这样从1号节点开始,每次转移,就能求出每个节点的情况了。
    自己注意:向最长路径上的点转移时,长度是不会加一的。

    具体看代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <vector>
     5 #define maxn 10100
     6 using namespace std;
     7 
     8 vector<int>G[maxn];
     9 vector<int>len[maxn];
    10 int N;
    11 int max1[maxn];//以1为根,i节点的最长路径
    12 int max2[maxn];//以1为根,i节点的次长路径,保证最长边的下一点不在这条路径上
    13 int max1id[maxn];
    14 int max2id[maxn];
    15 void init(){
    16     for(int i=0;i<=N;i++){
    17         G[i].clear();
    18         len[i].clear();
    19     }
    20 }
    21 bool vis[maxn];
    22 void dfs1(int u,int fa){
    23     max1[u]=0;
    24     max2[u]=0;
    25     for(int i=0;i<G[u].size();i++){
    26         int v=G[u][i];
    27         if (v==fa) continue;
    28         dfs1(v,u);
    29         if (max1[v]+len[u][i]>max2[u]){//这个方法真机智啊
    30             max2[u]=max1[v]+len[u][i];
    31             max2id[u]=v;
    32         }
    33         if (max1[u]<max2[u]){
    34             swap(max1[u],max2[u]);
    35             swap(max1id[u],max2id[u]);
    36         }
    37     }
    38     return;
    39 }
    40 void dfs2(int u,int fa){
    41     for(int i=0;i<G[u].size();i++){
    42         int v=G[u][i];
    43         if (v==fa) continue;
    44         //用u去更新v
    45         if (max1id[u]==v){
    46             if (max2[v]<max2[u]+len[u][i]){
    47                 max2[v]=max2[u]+len[u][i];
    48                 max2id[v]=u;
    49             }
    50         }else {
    51             if (max2[v]<max1[u]+len[u][i]){
    52                 max2[v]=max1[u]+len[u][i];
    53                 max2id[v]=u;
    54             }
    55         }
    56         if (max2[v]>max1[v]){
    57             swap(max2[v],max1[v]);
    58             swap(max2id[v],max1id[v]);
    59         }
    60         dfs2(v,u);
    61     }
    62     return ;
    63 }
    64 int main()
    65 {
    66     while(~scanf("%d",&N)){
    67         init();
    68         int v,c;
    69         for(int i=2;i<=N;i++){
    70             scanf("%d%d",&v,&c);
    71             G[i].push_back(v);
    72             G[v].push_back(i);
    73             len[i].push_back(c);
    74             len[v].push_back(c);
    75         }
    76         dfs1(1,-1);
    77         dfs2(1,-1);
    78         for(int i=1;i<=N;i++) printf("%d
    ",max1[i]);
    79     }
    80 
    81     return 0;
    82 }
    View Code
     

    POJ 4045

    题意:这个题大致意思是给你一颗树,让你求一点,使该点到其余各点的距离之和最小。如果这样的点有多个,则按升序依次输出。

    分析:cunt[x]记录以x为根的子树中节点的个数

            dp[x]记录以x为根时,x到所有节点的距离之和

            第一遍dfs处理这两个

            又是一道根节点转移的题目

    vsum=sum-cunt[v]-1+(N-cunt[v]-2)+1;
    sum是以当前节点u为根时的所求值,vsum是将根转移到v节点上,所以v节点形成的子树整体上移,深度都减少了1,而其他节点深度都增加了1,这个在纸上画一画就明白了。
    所以dfs就能搞定了

     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 #include <vector>
     5 #include <algorithm>
     6 #include <map>
     7 #include <string>
     8 #include <queue>
     9 #define LL long long
    10 #define maxn 51000
    11 using namespace std;
    12 vector<int>G[maxn];
    13 LL dp[maxn];
    14 LL cunt[maxn];
    15 bool vis[maxn];
    16 LL Min;
    17 int cnt=0;
    18 int ans[maxn];
    19 void init(){
    20     for(int i=0;i<maxn;i++) G[i].clear();
    21     memset(dp,0,sizeof(dp));
    22     memset(cunt,0,sizeof(cunt));
    23 }
    24 LL dfs1(int u){
    25     LL ans=0;
    26     for(int i=0;i<G[u].size();i++){
    27         int v=G[u][i];
    28         if (vis[v]) continue;
    29         vis[v]=true;
    30         ans+=dfs1(v)+1;
    31     }
    32     return cunt[u]=ans;
    33 }
    34 LL dfs2(int u){
    35     LL ans=0;
    36     for(int i=0;i<G[u].size();i++){
    37         int v=G[u][i];
    38         if (vis[v]) continue;
    39         vis[v]=true;
    40         ans+=dfs2(v)+1+cunt[v];
    41     }
    42     return dp[u]=ans;
    43 }
    44 LL sum1,cunt1;
    45 LL N,I,R;
    46 void dfs3(int u,LL sum){
    47     LL vsum=0;
    48     for(int i=0;i<G[u].size();i++){
    49         int v=G[u][i];
    50         if (vis[v]) continue;
    51         vsum=sum-cunt[v]-1+(N-cunt[v]-2)+1;
    52         if (vsum==Min) ans[cnt++]=v;
    53         if (vsum<Min) {
    54             cnt=0;
    55             ans[cnt++]=v;
    56             Min=vsum;
    57         }
    58         LL cu=cunt[u],cv=cunt[v];
    59         cunt[v]=N-1;
    60         cunt[u]=N-cv-2;
    61         vis[v]=true;
    62         dfs3(v,vsum);
    63         cunt[v]=cv,cunt[u]=cu;
    64     }
    65     return ;
    66 }
    67 int t;
    68 int main(){
    69     scanf("%d",&t);
    70     while(t--){
    71         init();
    72         scanf("%lld%lld%lld",&N,&I,&R);
    73         for(int i=1;i<=N-1;i++){
    74             int u,v;
    75             scanf("%d%d",&u,&v);
    76             G[u].push_back(v);
    77             G[v].push_back(u);
    78         }
    79         memset(vis,0,sizeof(vis));vis[1]=true;
    80         cunt1=dfs1(1);
    81         memset(vis,0,sizeof(vis));vis[1]=true;
    82         sum1=dfs2(1);
    83         Min=sum1;cnt=0;
    84         ans[cnt++]=1;
    85         memset(vis,0,sizeof(vis));vis[1]=true;
    86         dfs3(1,sum1);
    87         sort(ans,ans+cnt);
    88         printf("%lld
    ",Min*I*I*R);
    89         for(int i=0;i<cnt;i++){
    90             if (i==cnt-1) printf("%d
    ",ans[i]);
    91             else printf("%d ",ans[i]);
    92         }
    93         printf("
    ");
    94     }
    95     return 0;
    96 }
    View Code
    
    

    POJ 3342

    题意:和第二题很想,父亲和孩子不能都选择,但是要判断选择的方案是否唯一

    分析:讨论一下新增部分,

    新增dup[x][0]、dup[x][1]分别表示选与不选是否唯一

    memset(dup,0,sizeof(dup));//1表示确定,0不确定
    其中v就是son节点
    if ((dp[v][0]>dp[v][1]&&dup[v][0]==0)||(dup[v][1]>dup[v][0]&&dup[v][1]==0)||(dp[v][1]==dp[v][0]))
                        dup[u][0]=0;
    if (dup[v][0]==0) dup[u][1]=0;
    我们判断dp[v][0]和dp[v][1]哪个大,这样dup[v][0]的状态就延续上去了(当然是必然选择的那个状态延续),当然若dp[v][1]==dp[v][0],dup就是0了
    dup需要赋初值1已做标记
      1 #include <iostream>
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include <vector>
      5 #include <map>
      6 #include <string>
      7 #include <queue>
      8 #define maxn 310
      9 using namespace std;
     10 //map存储标号
     11 //边读边记录边的关系
     12 //bfs分层记录每层节点
     13 //从底层向上层dp
     14 vector<int> G[maxn];
     15 vector<int> Ceil[maxn];
     16 map<string,int>Mp;
     17 int n,cnum,cnt;//人数,分层数
     18 void init(){
     19     for(int i=0;i<maxn;i++) G[i].clear();
     20     for(int i=0;i<maxn;i++) Ceil[i].clear();
     21     cnum=0;cnt=0;
     22     Mp.clear();
     23     return ;
     24 }
     25 typedef pair<int,int>PAIR;
     26 bool vis[maxn];
     27 void Bfs(){
     28     queue<PAIR> Q ;
     29     Q.push(make_pair(1,1));
     30     memset(vis,0,sizeof(vis));
     31     vis[1]=true;
     32     while(!Q.empty()){
     33         PAIR New=Q.front();
     34         Q.pop();
     35         int u=New.first;
     36         int st=New.second;
     37         Ceil[st].push_back(u);
     38         cnum=max(cnum,st);
     39         for(int i=0;i<G[u].size();i++){
     40             int v=G[u][i];
     41             if (vis[v]) continue;
     42             Q.push(make_pair(v,st+1));
     43             vis[v]=true;
     44         }
     45     }
     46     return;
     47 }
     48 int dp[maxn][2];//0表示不选择i节点,1表示选择i节点
     49 int dup[maxn][2];
     50 void solve(){
     51     memset(dup,0,sizeof(dup));//1表示确定,0不确定
     52     memset(dp,0,sizeof(dp));
     53     for(int i=0;i<Ceil[cnum].size();i++){
     54         int u=Ceil[cnum][i];
     55         dp[u][0]=0;dp[u][1]=1;
     56         dup[u][0]=dup[u][1]=1;
     57     }
     58     for(int i=cnum-1;i>=1;i--){
     59         for(int j=0;j<Ceil[i].size();j++){
     60             int u=Ceil[i][j];
     61             dup[u][0]=dup[u][1]=1;
     62             for(int k=0;k<G[u].size();k++){
     63                 int v=G[u][k];
     64                 dp[u][0]+=max(dp[v][0],dp[v][1]);
     65                 dp[u][1]+=dp[v][0];
     66                 if ((dp[v][0]>dp[v][1]&&dup[v][0]==0)||(dup[v][1]>dup[v][0]&&dup[v][1]==0)||(dp[v][1]==dp[v][0]))
     67                     dup[u][0]=0;
     68                 if (dup[v][0]==0) dup[u][1]=0;
     69             }
     70             dp[u][1]++;
     71         }
     72     }
     73     if (dp[1][0]==dp[1][1]){
     74         printf("%d No
    ",dp[1][0]);
     75     }
     76     if (dp[1][0]>dp[1][1]){
     77         printf("%d ",dp[1][0]);
     78         if (dup[1][0]) puts("Yes");else puts("No");
     79     }
     80     if (dp[1][1]>dp[1][0]){
     81         printf("%d ",dp[1][1]);
     82         if (dup[1][1]) puts("Yes");else puts("No");
     83     }
     84     return;
     85 }
     86 int main(){
     87     string s;
     88     char s1[55],s2[55];
     89     while(~scanf("%d",&n)&&n){
     90         init();
     91         scanf("%s",s1);
     92         Mp[s=s1]=++cnt;
     93         for(int i=1;i<n;i++){
     94             scanf("%s",s1);scanf("%s",s2);
     95             int u,v;
     96             if (Mp.count(s=s1)) u=Mp[s=s1];
     97             else u=Mp[s=s1]=++cnt;
     98             if (Mp.count(s=s2)) v=Mp[s=s2];
     99             else v=Mp[s=s2]=++cnt;
    100             G[v].push_back(u);
    101         }
    102         Bfs();//分层
    103         solve();
    104     }
    105     return 0;
    106 }
    View Code
    
    
  • 相关阅读:
    iSeries存储过程笔记
    最近做得的网站
    两个iSeries存储过程的示例
    索引的怪异问题
    Saas的概念感触
    asp.net 2.0的TextBox遭遇ReadOnly=True时ViewState不回传的问题
    网上看到的一句诗
    DB2/400到Oracle的迁移
    如何往自己的网站增加Asp.net Ajax
    default关键字作用
  • 原文地址:https://www.cnblogs.com/little-w/p/3858654.html
Copyright © 2020-2023  润新知