这题做的心塞。。。

整个思路非常清晰,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. MQTT的学习研究(四)moquette-mqtt 的使用之mqtt Blocking API客户端订阅并接收主题信息

    在上面两篇关于mqtt的broker的启动和mqtt的服务端发布主题信息之后,我们客户端需要订阅相关的信息并接收相关的主题信息. package com.etrip.mqtt; import java ...

  2. mybatis-config.xml配置

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  3. Activity工作流入门之HelloWorld

    Activity的在线安装地址为:http://www.activiti.org/designer/update/ 打开Eclipse -> Help -> Install New Sof ...

  4. log4j配置输出到多个日志文件(转)

    參考资料:http://logging.apache.org/log4j/1.2/manual.html 通常我们项目里,有一些重要的日志想单独的输出到指定的文件,而不是全总输出到系统的日志文件中.那 ...

  5. 徐州网络赛F-Feature Trace【暴力】

    Morgana is learning computer vision, and he likes cats, too. One day he wants to find the cat moveme ...

  6. 南京网络赛B-The writing on the wall

    30.43% 2000ms 262144K Feeling hungry, a cute hamster decides to order some take-away food (like frie ...

  7. 您好,python的请求es的http库是urllib3, 一个请求到贵司的es节点,想了解下,中间有哪些网关啊?冒昧推测,贵司的部分公共网关与python-urllib3的对接存在异常?

    您好,python的请求es的http库是urllib3, 一个请求到贵司的es节点,想了解下,中间有哪些网关啊?冒昧推测,贵司的部分公共网关与python-urllib3的对接存在异常? 负载均衡( ...

  8. MySQL 慢查询日志工具之pt-query-digest

    1. 工具简介 pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog.General log.slowlog,也可以通过SHOWPROCESSLIST或者通过tc ...

  9. openstack配置域名访问

    #openstack配置域名访问 openstack pike 安装 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html #主要是在默认配置的基础上,做了个 ...

  10. Mybatis三剑客之mybatis-plugin

    搜索mybatis plugin并安装. 如果没有的话,就按照如下: 1. 简介     mybatis plugin作为一款优秀的mybatis跳转插件,比起free mybatis plugin插 ...