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

Vijos p1770 大内密探 树形DP+计数

时间:2016-01-08 23:32:25      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:

  4天终于做出来了,没错我就是这么蒟蒻。教训还是很多的。

  建议大家以后编树形DP不要用记忆化搜索,回溯转移状态个人感觉更有条理性。

  大神题解传送门 by iwtwiioi

  我的题解大家可以看注释"//"部分

  本题我用的树形DP中dp[x][fa][need]表示编号为x的节点的父亲选(1)没选(0),x的父亲需(1)不需要(0)其他节点来覆盖。

若父亲节点选了,则need肯定为0,所以不存在fa==1而need==1的状态,相当于浪费了¼的空间。毕竟数据范围比较小,而且程序要有可读性!程序要有可读性!程序要有可读性!我这么写代码不是加强了程序的可读性吗?像iwtwiioi那样用012表示状态题解和程序的可读性大大降低,大家在读题解时难免要费点劲。并没有贬义技术分享!!!╮(╯_╰)╭


技术分享

my code:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 int point[100003],next[200003],v[200003],cnt=0,N,l[100003],r[100003],pre[100003],con[100003];
  6 const long long mo=1000000007;
  7 long long f[100003][2][2];
  8 int dp[100003][2][2];
  9 bool p[100003];
 10 void memsetf(){for(int i=0;i<=N;++i)for(int j=0;j<2;++j)for (int k=0;k<2;++k)f[i][j][k]=1;}
 11 void insect(int x,int y){next[cnt]=point[x];point[x]=cnt;v[cnt]=y;cnt++;}
 12 void dfs(int x)
 13 {
 14     if (x==0) return;
 15     int i,j=0;
 16     for (i=point[x];i!=-1;i=next[i])
 17      if (p[v[i]]==0)
 18      {
 19          p[v[i]]=1;
 20          if (l[x]==0) {l[x]=v[i];j=v[i];}
 21          else {r[j]=v[i];pre[v[i]]=j;j=v[i];}
 22      }
 23     dfs(j); con[j]=con[l[j]]+1;
 24     while (pre[j]!=-1){j=pre[j]; dfs(j); con[j]=con[l[j]]+con[r[j]]+1;}
 25 }
 26 void work(int x)
 27 {
 28     if (r[x]!=0) work(r[x]);
 29     if (l[x]!=0) work(l[x]);
 30     long long s=0; int num=1000000008;
 31     if ((l[x]==0)&&(r[x]==0))
 32     {
 33         dp[x][0][1]=1; dp[x][0][0]=1; dp[x][1][0]=0; return;
 34     }
 35     else
 36     if (l[x]==0)
 37     {
 38         dp[x][0][1]=1+dp[r[x]][0][0]; f[x][0][1]=f[r[x]][0][0];
 39         dp[x][0][0]=1+dp[r[x]][0][0]; f[x][0][0]=f[r[x]][0][0];
 40         dp[x][1][0]=dp[r[x]][1][0]; f[x][1][0]=f[r[x]][1][0];
 41         return;
 42     }
 43     else
 44     if (r[x]==0)
 45     {
 46         dp[x][0][1]=1+dp[l[x]][1][0]; f[x][0][1]=f[l[x]][1][0];
 47         //dp[x][0][0]=min(1+dp[l[x]][1][0],dp[l[x]][0][1]);
 48         if (1+dp[l[x]][1][0]<dp[l[x]][0][1])
 49          dp[x][0][0]=1+dp[l[x]][1][0],f[x][0][0]=f[l[x]][1][0];
 50         else
 51          if (1+dp[l[x]][1][0]>dp[l[x]][0][1])
 52           dp[x][0][0]=dp[l[x]][0][1],f[x][0][0]=f[l[x]][0][1];
 53          else
 54           dp[x][0][0]=dp[l[x]][0][1],f[x][0][0]=(f[l[x]][1][0]+f[l[x]][0][1])%mo;
 55         //dp[x][1][0]=min(1+dp[l[x]][1][0],dp[l[x]][0][0]);
 56         if (1+dp[l[x]][1][0]<dp[l[x]][0][0])
 57          dp[x][1][0]=1+dp[l[x]][1][0],f[x][1][0]=f[l[x]][1][0];
 58         else
 59          if (1+dp[l[x]][1][0]>dp[l[x]][0][0])
 60           dp[x][1][0]=dp[l[x]][0][0],f[x][1][0]=f[l[x]][0][0];
 61          else
 62           dp[x][1][0]=dp[l[x]][0][0],f[x][1][0]=(f[l[x]][1][0]+f[l[x]][0][0])%mo;
 63         return;
 64     }
 65     //dp[x][0][1]=min(dp[x][0][1],dp[l[x]][0][1]+dp[r[x]][0][1]);
 66     //dp[x][0][1]=min(dp[x][0][1],1+dp[l[x]][1][0]+dp[r[x]][0][0]);
 67     if (dp[l[x]][0][1]+dp[r[x]][0][1]<1+dp[l[x]][1][0]+dp[r[x]][0][0])
 68      dp[x][0][1]=dp[l[x]][0][1]+dp[r[x]][0][1],f[x][0][1]=(f[l[x]][0][1]*f[r[x]][0][1])%mo;
 69     else
 70      if (dp[l[x]][0][1]+dp[r[x]][0][1]>1+dp[l[x]][1][0]+dp[r[x]][0][0])
 71       dp[x][0][1]=1+dp[l[x]][1][0]+dp[r[x]][0][0],f[x][0][1]=(f[l[x]][1][0]*f[r[x]][0][0])%mo;
 72      else
 73       {
 74           dp[x][0][1]=1+dp[l[x]][1][0]+dp[r[x]][0][0];
 75         f[x][0][1]=((f[l[x]][0][1]*f[r[x]][0][1])%mo+(f[l[x]][1][0]*f[r[x]][0][0])%mo)%mo;
 76       }
 77     //dp[x][0][0]=min(dp[x][0][0],dp[l[x]][0][1]+dp[r[x]][0][0]);
 78     //dp[x][0][0]=min(dp[x][0][0],1+dp[l[x]][1][0]+dp[r[x]][0][0]);
 79     if (dp[l[x]][0][1]+dp[r[x]][0][0]<1+dp[l[x]][1][0]+dp[r[x]][0][0])
 80      dp[x][0][0]=dp[l[x]][0][1]+dp[r[x]][0][0],f[x][0][0]=(f[l[x]][0][1]*f[r[x]][0][0])%mo;
 81     else
 82      if (dp[l[x]][0][1]+dp[r[x]][0][0]>1+dp[l[x]][1][0]+dp[r[x]][0][0])
 83       dp[x][0][0]=1+dp[l[x]][1][0]+dp[r[x]][0][0],f[x][0][0]=(f[l[x]][1][0]*f[r[x]][0][0])%mo;
 84      else
 85       {
 86           dp[x][0][0]=1+dp[l[x]][1][0]+dp[r[x]][0][0];
 87           f[x][0][0]=((f[l[x]][1][0]*f[r[x]][0][0])%mo+(f[l[x]][0][1]*f[r[x]][0][0])%mo)%mo;
 88       }
 89     //dp[x][1][0]=min(dp[x][1][0],dp[l[x]][0][0]+dp[r[x]][1][0]);
 90     //dp[x][1][0]=min(dp[x][1][0],1+dp[l[x]][1][0]+dp[r[x]][1][0]);
 91     if (dp[l[x]][0][0]+dp[r[x]][1][0]<1+dp[l[x]][1][0]+dp[r[x]][1][0])
 92      dp[x][1][0]=dp[l[x]][0][0]+dp[r[x]][1][0],f[x][1][0]=(f[l[x]][0][0]*(f[r[x]][1][0]))%mo;
 93     else
 94      if (dp[l[x]][0][0]+dp[r[x]][1][0]>1+dp[l[x]][1][0]+dp[r[x]][1][0])
 95       dp[x][1][0]=1+dp[l[x]][1][0]+dp[r[x]][1][0],f[x][1][0]=(f[l[x]][1][0]*f[r[x]][1][0])%mo;
 96      else
 97       {
 98           dp[x][1][0]=1+dp[l[x]][1][0]+dp[r[x]][1][0];
 99           f[x][1][0]=((f[l[x]][0][0]*(f[r[x]][1][0]))%mo+(f[l[x]][1][0]*f[r[x]][1][0])%mo)%mo;
100       }
101 }
102 int main()
103 {
104     memset(point,-1,sizeof(point));
105     memset(next,-1,sizeof(next));
106     memset(pre,-1,sizeof(pre));
107     memset(dp,50,sizeof(dp));
108     memset(v,0,sizeof(v));
109     memset(p,0,sizeof(p));
110     memset(l,0,sizeof(l));
111     memset(r,0,sizeof(r));
112     scanf("%d\n",&N);
113     memsetf();
114     int i,x,y;
115     for (i=1;i<N;++i)
116     {
117         scanf("%d %d\n",&x,&y);
118         insect(x,y);insect(y,x);
119     }p[1]=1;dfs(1);
120     work(l[1]);
121     if (dp[l[1]][0][1]<(1+dp[l[1]][1][0]))
122      printf("%d\n%I64d\n",dp[l[1]][0][1],f[l[1]][0][1]);
123     else
124      if (dp[l[1]][0][1]>(1+dp[l[1]][1][0]))
125       printf("%d\n%I64d\n",1+dp[l[1]][1][0],f[l[1]][1][0]);
126      else
127       printf("%d\n%I64d\n",1+dp[l[1]][1][0],(f[l[1]][0][1]+f[l[1]][1][0])%mo);
128     return 0;
129 }

 

 

 

P1770大内密探
 
 

背景

大内密探,负责秘密保护皇上,还有保护皇宫内外一切产业。——大内密探零零七

描述

在古老的皇宫中,有N个房间以及N-1条双向通道,每条通道连接着两个不同的房间,所有的房间都能互相到达。皇宫中有许多的宝物,所以需要若干个大内密探来守护。一个房间被守护当切仅当该房间内有一名大内密探或者与该房间直接相邻的房间内有大内密探。

现在身为大内密探零零七的你想知道要把整个皇宫守护好至少需要多少名大内密探以及有多少种安排密探的方案。两种方案不同当且仅当某个房间在一种方案有密探而在另一个方案内没有密探。

格式

输入格式

第一行一个正整数N.(1<=N<=100000)
后面N-1行,每行两个正整数a和b,表示房间a和房间b之间有一条无向通道。

房间的编号从1到N

输出格式

第一行输出正整数K,表示最少安排的大内密探。

第二行输出整数S,表示有多少种方案安排最少的密探,由于结果可能较大,请输出方案数mod 1000000007的余数。

样例1

样例输入1[复制]

 
7
2 1
3 1
4 2
5 1
6 2
7 6

样例输出1[复制]

 
3
4

限制

每个测试点1s

提示

30%保证:n <= 10
70%保证:n <= 1000
100%保证:n <= 100000

 

Vijos p1770 大内密探 树形DP+计数

标签:

原文地址:http://www.cnblogs.com/abclzr/p/5115049.html

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