这题做的心塞。。。

整个思路非常清晰,d[i][0]表示第i个结点不设置监察的情况下至少需要的数量;d[i][1]表示第i个结点设置检查的情况下的最小需要的数量。

状态转移方程见代码。

但是万万没想到的是,在实现过程中修改了4遍代码,wa了若干次才AC。。。。

下面来总结一下各种wa代码:

版本1:开二维数组存储树(本质上是邻接矩阵存储,把树存储成图),报错TLE。这时候第一感觉是每次更新d[i]的时候都需要遍历一遍邻接表中的所有结点不管是否是子节点都需要遍历。也就是完整的n*n复杂度。因此有了第一次修改,考虑存储的时候用vector只存储子节点从而减少遍历时的数量。(见版本2)

上代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<algorithm>
using namespace std;
//TLE 应该是在更新d[i][]的时候每次都需要遍历n个数,复杂度为o(n^2)
const int maxn=;
int d[maxn][];
int gra[maxn][maxn];
int flag[maxn];
int n;
void dp(int cur){
flag[cur]=;
if(d[cur][]>=||d[cur][]>=){
return;
}
int leaf=;
for(int i=;i<n;i++){
if(gra[cur][i]&&flag[i]!=){
leaf=;
dp(i);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[i][];
d[cur][]+=min(d[i][],d[i][]);
}
}
d[cur][]++;
if(leaf==){
d[cur][]=;d[cur][]=;
}
}
int main(void){
while(scanf("%d",&n)){
memset(flag,,sizeof(flag));
memset(gra,,sizeof(gra));
memset(d,-,sizeof(d));
int x,cnt;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
while(cnt--){
int tem;
scanf("%d",&tem);
gra[x][tem]=;
gra[tem][x]=;
}
}
dp(x);
int ans=min(d[x][],d[x][]);
cout<<ans<<endl;
}
return ;
}

版本2代码:拟通过vector减少遍历的结点个数(只遍历子节点)。这次修改后果然没有报TLE,但是报了另外一个错:MLE。。。

所以说使用stl还是要慎重。。这时再看了一遍输入样例,发现其实这个输入是按标准的有向树输入的;换句话说根本不需要构造图来解,只需要每个结点记录其父亲即可。

这样一算,存储的数据量瞬间减半。因此有了版本3代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<vector>
using namespace std;
//memory limit
const int maxn=;
int d[maxn][];
//int gra[maxn][maxn];
vector<int>gra[maxn];
bool flag[maxn];
int n;
void dp(int cur){
flag[cur]=;
if(d[cur][]>=||d[cur][]>=){
return;
}
else{
int leaf=;
for(int i=;i<gra[cur].size();i++){
int next=gra[cur][i];
if(flag[next]==){
leaf=;
dp(next);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[next][];
d[cur][]+=min(d[next][],d[next][]);
}
}
d[cur][]++;
if(leaf==){
d[cur][]=;d[cur][]=;
}
}
}
int main(void){
while(scanf("%d",&n)!=EOF){
memset(flag,,sizeof(flag));
memset(gra,,sizeof(gra));
memset(d,-,sizeof(d));
int x,cnt;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
while(cnt--){
int tem;
scanf("%d",&tem);
gra[x].push_back(tem);
gra[tem].push_back(x);
}
}
dp(x);
int ans=min(d[x][],d[x][]);
cout<<ans<<endl;
}
return ;
}

版本3代码:本来以为这个可以直接AC的,结果又一次TLE。。。而且这次的错误找了好久没想到。

最后发现出现在了scanf上。。。

版本3中的代码while(scanf("%d",&n)) 改成while(scanf("%d",&n)!=EOF)或者while(~scanf("%d",&n))就AC了(真的是,秀了一波骚操作。侧面反映基础不太扎实。。。。)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int d[maxn][];
int pre[maxn];
int childcnt[maxn];
int n;
void dp(int cur){
if(d[cur][]>=||d[cur][]>=){
return;
}
if(childcnt[cur]==){
d[cur][]=;d[cur][]=;
return ;
}
for(int i=;i<n;i++){
if(pre[i]==cur){
dp(i);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[i][];
d[cur][]+=min(d[i][],d[i][]);
}
}
d[cur][]++;
}
int main(void){
while(scanf("%d",&n)){
memset(pre,-,sizeof(pre));
memset(d,-,sizeof(d));
int x,cnt,root=-;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
childcnt[x]=cnt;
if(root==-)root=x;
while(cnt--){
int tem;
scanf("%d",&tem);
pre[tem]=x;
if(tem==root){
root=x;
}
}
}
dp(root);
int ans=min(d[root][],d[root][]);
printf("%d\n",ans);
}
return ;
}

AC代码如下:哎,任重而道远,,,太菜了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int d[maxn][];
int pre[maxn];
int childcnt[maxn];
int n;
void dp(int cur){
if(d[cur][]>=||d[cur][]>=){
return;
}
if(childcnt[cur]==){
d[cur][]=;d[cur][]=;
return ;
}
for(int i=;i<n;i++){
if(pre[i]==cur){
dp(i);
if(d[cur][]==-)d[cur][]=;
if(d[cur][]==-)d[cur][]=;
d[cur][]+=d[i][];
d[cur][]+=min(d[i][],d[i][]);
}
}
d[cur][]++;
}
int main(void){
while(scanf("%d",&n)!=EOF){//万万没想到是这里出错
memset(pre,-,sizeof(pre));
memset(d,-,sizeof(d));
int x,cnt,root=-;
int num=n;
while(num--){
scanf("%d:(%d)",&x,&cnt);
childcnt[x]=cnt;
if(root==-)root=x;
while(cnt--){
int tem;
scanf("%d",&tem);
pre[tem]=x;
if(tem==root){
root=x;
}
}
}
dp(root);
int ans=min(d[root][],d[root][]);
printf("%d\n",ans);
}
return ;
}

POJ - 1463 Strategic game (树状动态规划)的更多相关文章

  1. POJ 2352 Stars(树状数组)

    Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30496   Accepted: 13316 Descripti ...

  2. POJ 3321 Apple Tree (树状数组+dfs序)

    题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...

  3. poj 2828 Buy Tickets(树状数组 | 线段树)

    题目链接:poj 2828 Buy Tickets 题目大意:给定N,表示有个人,给定每一个人站入的位置,以及这个人的权值,如今按队列的顺序输出每一个人的权值. 解题思路:第K大元素,非常巧妙,将人入 ...

  4. poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)

    题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...

  5. poj 2299 Ultra-QuickSort(树状数组求逆序数)

    链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...

  6. poj 3067 Japan(树状数组求逆序数)

    链接:http://poj.org/problem?id=3067 题意:左边有n个城市,右边有m个城市,建k条道路,问有这k条道路中有多少个交点. 分析:将城市按x和y从小到大排序,对于每条道路,求 ...

  7. POJ 2299 Ultra-QuickSort(树状数组+离散化)

    http://poj.org/problem?id=2299 题意:给出一组数,求逆序对. 思路: 这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理. 这道题目的数据可以大到999,9 ...

  8. POJ 3067 Japan 【树状数组经典】

    题目链接:POJ 3067 Japan Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32076   Accep ...

  9. POJ 2155 Matrix(树状数组+容斥原理)

    [题目链接] http://poj.org/problem?id=2155 [题目大意] 要求维护两个操作,矩阵翻转和单点查询 [题解] 树状数组可以处理前缀和问题,前缀之间进行容斥即可得到答案. [ ...

随机推荐

  1. 关于线上js报错问题的思考

    1.有没有可能对线上报错进行实时监控,只要线上报错出现就会以邮件的形式发出来. 2.有没有可能将每个模块和开发者联系起来,只要报错就直接报给开发者

  2. Excel 2010 Alt+; (分号) --- “只选定当前选定区域中的可视单元格”

    excel怎样把筛选出来的加上颜色? 1.选中筛选结果数据区域: 2.同时按下Alt+; (分号)键,选中筛选出的数据: 3.鼠标右键,设置单元格格式: 4.在弹出的对话框中,设置字体.背景颜色,即可 ...

  3. Sql Server 关于列名带中括号"[]"的问题

    1.如果列名为数据库的关键字则自动加上中括号“[]” 例如[level] 2.如果列名中带有特殊符号.[date(a)] 数据存储的过程: 1.在添加数据的时候:要带有中括号,有必要在添加参数的时候不 ...

  4. 纯HTML自动刷新页面或重定向(http-equiv属性的refresh)

    refresh 属性值  --  刷新与跳转(重定向)页面 refresh出现在http-equiv属性中,使用content属性表示刷新或跳转的开始时间与跳转的网址 refresh示例一:5秒之后刷 ...

  5. angularJS的路由!

    angularJS 路由:(分发需求) angularJS 中路由是单独提供的功能模块,ngRoute  也是一个单独发行的文件 可以通过 npm 去安装这个包:angular-route <s ...

  6. 170727、MySQL查询性能优化

    MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...

  7. 用Squid实现反向代理

    Last-Modified: 告诉反向代理页面什么时间被修改 Expires: 告诉反向代理页面什么时间应该从缓冲区中删除 Cache-Control: 告诉反向代理页面是否应该被缓冲 Pragma: ...

  8. Educational Codeforces Round 28

    A. Curriculum Vitae 题目链接:http://codeforces.com/contest/846/problem/A 题目意思:给你一个只包含0-1的数组,现在要求去可以去掉一些元 ...

  9. Tensorflow中卷积的padding方式

    根据tensorflow中的Conv2D函数,先定义几个基本符号: 输入矩阵W*W,这里只考虑输入宽高相等的情况,如果不相等,推导方法一样 filter矩阵F*F,卷积核 stride值S,步长 输出 ...

  10. Mirror--程序访问镜像数据库的超时机制

    程序在访问有镜像的数据库和无镜像的数据库时,采用的链接超时时间算法不一样,因此会导致在在有镜像的数据库上设置了15 S的超时时间,而实际的超时时间仅为3.6 S,从而导致有镜像的数据库更容易超时. 在 ...