洛谷 P2279 [HNOI2003]消防局的设立
来源:互联网 发布:积分系统数据库设计 编辑:程序博客网 时间:2024/05/20 08:26
P2279 [HNOI2003]消防局的设立
法一:
某贪心方法(摘自洛谷题解):一般的,对于深度最大的结点u,选择u的k级祖先是最划算的(意思是说这个题目的2改成了k我们都是可以做的,至于这个结论,详见刘汝佳的《***入门经典》(蓝书P35),还有一个例题,不过和本题不一样)
法二:
//树形dp/*状态的设计:f[i][0]: 表示选了自己以后...f[i][1]: 表示选了儿子以后...f[i][2]: 表示选了孙子以后...——上面用来表示这个点被覆盖了的状态,下面为这个点没有被覆盖的状态f[i][3]: 表示自己不一定被覆盖,但是儿子一定全部被覆盖时...f[i][4]: 表示自己和儿子都不一定被覆盖,但是孙子一定全部都被覆盖时......=>最少的消防局数 i表示当前点,j表示所有有从i开始的边指向的点f[i][0]=Σmin(f[j][0..4])+1f[i][1]=min(f[k][0]+Σ(j!=k)min(f[j][0..3]))//k表示j中任何一个点,min(f[j][0..3])是由于没有选i、j点,而选了k点,因此j点能被覆盖,但如果要是j的子结点被覆盖,则需要0-3情况来满足//min(f[k][0]..)是由于可能是任意一个儿子结点被选f[i][2]=min(f[k][1]+Σ(j!=k)min(f[j][0..2])//可能是任意一个儿子结点的子节点被选//由于没有选i、j、k点,j点没有被覆盖,要是它被覆盖则需要0-2情况//举例:min(f[j][0..3])表示min(f[j][0],f[j][1],f[j][2],f[j][3])f[i][3]=Σmin(f[j][0..2])//所有的min都是对0..x生效,Σ对j生效f[i][4]=Σmin(f[j][0..3])简化: f[i][1]=min(Σmin(f[j][0..3])+f[k][0]-min(f[k][0..3]))=min(f[k][0]-min(f[k][0..3]))+Σmin(f[j][0..3])f[i][2]=min(Σmin(f[j][0..2])+f[k][1]-min(f[k][0..2]))=min(f[k][1]-min(f[k][0..2]))+Σmin(f[j][0..2])可以由此想到预处理令p[j][p]=min(f[j][0..p])(p>=2) (并非答案,只是方便计算)则f[i][0]=Σp[j][4]+1f[i][1]=Σp[j][3]+min(f[k][0]-p[k][3])f[i][2]=Σp[j][2]+min(f[k][1]-p[k][2])f[i][3]=Σp[j][2]f[i][4]=Σp[j][3]则f[i][1]=f[i][4]+min(f[k][0]-p[k][3])f[i][2]=f[i][3]+min(f[k][1]-p[k][2])实际上,不用另开p数组,直接在f中存储即可,后面会直接覆盖掉*/ //类似于最小支配集(在树中选出一些点,使得没有选出的点都与选出的点直接相连,要求选的点尽可能少)#include<cstdio>#include<algorithm>using namespace std;struct Edge{ int to,next;}edge[2100];int node[1100],edge_num,n;int f[1100][5];void make(int x,int y){ edge[++edge_num].to=y; edge[edge_num].next=node[x]; node[x]=edge_num;}void dfs(int x){ int k=node[x],i,j,y,t1=0x3f3f3f3f,t2=0x3f3f3f3f;//优化版本 f[x][0]=1; while(k!=0) { y=edge[k].to; dfs(y); f[x][0]+=f[y][4]; f[x][3]+=f[y][2]; f[x][4]+=f[y][3]; t1=min(t1,f[y][0]-f[y][3]); t2=min(t2,f[y][1]-f[y][2]); k=edge[k].next; } f[x][1]=f[x][4]+t1; f[x][2]=min(min(f[x][0],f[x][1]),t2+f[x][3]); f[x][3]=min(f[x][2],f[x][3]); f[x][4]=min(f[x][3],f[x][4]);// int k=node[x],i,j,y;// while(k!=0)// {// y=edge[k].to;// dfs(y);// for(i=2;i<=4;i++)// for(j=0;j<i;j++)// f[y][i]=min(f[y][i],f[y][j]);// f[x][0]+=f[y][4];// f[x][3]+=f[y][2];// f[x][4]+=f[y][3];// k=edge[k].next;// }// f[x][0]++;// k=node[x];// f[x][1]=0x3f3f3f3f;f[x][2]=0x3f3f3f3f;// while(k!=0)// {// y=edge[k].to;// f[x][1]=min(f[x][1],f[y][0]-f[y][3]);// f[x][2]=min(f[x][2],f[y][1]-f[y][2]);// k=edge[k].next;// }// f[x][1]+=f[x][4];// f[x][2]+=f[x][3];}int main(){ int i,t; scanf("%d",&n); for(i=2;i<=n;i++) { scanf("%d",&t); make(t,i); } dfs(1); printf("%d",f[1][2]); //此时f[1][2]已经是min(f[1][0..2])了 return 0;}
阅读全文
0 0
- 洛谷 P2279 [HNOI2003]消防局的设立
- 洛谷 P2279 [HNOI2003]消防局的设立
- 洛谷 P2279 [HNOI2003]消防局的设立
- 洛谷 P2279 [HNOI2003]消防局的设立
- 洛谷 P2279 [HNOI2003]消防局的设立
- P2279 [HNOI2003]消防局的设立
- P2279 [HNOI2003]消防局的设立
- 洛谷P2279 [HNOI2003]消防局的设立(深搜,贪心)
- [HNOI2003]消防局的设立
- bzoj1217: [HNOI2003]消防局的设立
- bzoj1217: [HNOI2003]消防局的设立
- bzoj1217: [HNOI2003]消防局的设立
- 1217: [HNOI2003]消防局的设立
- bzoj1217 [HNOI2003]消防局的设立
- luoguP2279 [HNOI2003]消防局的设立
- 洛谷 2279 [HNOI2003] 消防局的设立 贪心+dfs
- 【bzoj 1217】[HNOI2003]消防局的设立 贪心
- BZOJ 1217: [HNOI2003]消防局的设立 贪心
- CC2541 IIC
- 1.12Android 学习+进度之十二-聊天UI升级
- unity多语言功能
- Git学习笔记(二)--团队协作
- Android Wi-Fi Firmware(wcnss)修改方法(以QCOM为平台)
- 洛谷 P2279 [HNOI2003]消防局的设立
- Android-内存泄漏巧妙解决
- Curl 相关参数用法
- [E10]展BOM
- JavaScript DOM编程艺术 第2版pdf
- 深入探讨Java中的异常与错误处理
- 51nod 1293 球与切换器
- 从Outlook导出联系人到VCF文件
- ZCMU—1374