[NOIP2003] 传染病控制 搜索+剪枝

搜索的最广泛应用优化——剪枝

这道题的dp和贪心都是无正确性的,所以,搜~~~~~~~

搜的时候你发现不剪枝极容易被卡掉(然而良心NOIP没有这么做,不剪枝仍然飞快),所以我们需要一些玄学的剪枝最常见的有俩:I.我们一层一层累加被感染人群若当前被感染人群已经大于已知解那么就舍去。 II.之后的每一层如果都取最大仍不如已知解优则舍去。

玄学.........

#include <cstdio>
#include <vector>
#include <algorithm>
#define MAXN 310
namespace pre{
  inline void read(int &sum){
    register char ch=getchar();
    for(sum=0;ch<‘0‘||ch>‘9‘;ch=getchar());
    for(;ch>=‘0‘&&ch<=‘9‘;sum=(sum<<1)+(sum<<3)+ch-‘0‘,ch=getchar());
  }
  inline int Max(int x,int y){
    return x>y?x:y;
  }
  int ans;
}
namespace tree{
  struct tree{
    int to,next;
  }c[MAXN<<1];
  int head[MAXN],t,size[MAXN],f[MAXN],Deep_Max,Max[MAXN];
  bool did[MAXN];
  std::vector<int> floor[MAXN];
  inline int comp(int x,int y){
    return size[x]>size[y];
  }
  inline void add(int x,int y){
    c[++t].to=y;
    c[t].next=head[x];
    head[x]=t;
  }
  inline void dfs(int x,int fa,int deep){
    Deep_Max=pre::Max(deep,Deep_Max);
    size[x]=1;
    f[x]=fa;
    floor[deep].push_back(x);
    for(int i=head[x];i;i=c[i].next)
      if(c[i].to!=fa)
        dfs(c[i].to,x,deep+1),size[x]+=size[c[i].to];
  }
  inline void Dfs(int deep,int ans){
    //if(ans+Max[deep+1]<=pre::ans)return;
    pre::ans=pre::Max(ans,pre::ans);
    if(deep==Deep_Max)return;
    for(int i=0;i<floor[deep+1].size();i++)
      if(did[f[floor[deep+1][i]]])
        did[floor[deep+1][i]]=1;
    for(int i=0;i<floor[deep+1].size();i++)
      if(did[floor[deep+1][i]]==0){
        did[floor[deep+1][i]]=1;
        Dfs(deep+1,ans+size[floor[deep+1][i]]);
        did[floor[deep+1][i]]=0;
      }
    for(int i=0;i<floor[deep+1].size();i++)
      if(did[f[floor[deep+1][i]]])
        did[floor[deep+1][i]]=0;
  }
}
namespace mid{
  int n,m;
  inline void Init(){
    using pre :: read;
    using tree :: add;
    read(n),read(m);
    for(int i=1,a,b;i<=m;i++)
      read(a),read(b),add(a,b),add(b,a);
    tree :: dfs(1,0,1);
  }
  inline void Work(){
    using namespace tree;
    for(int i=Deep_Max;i>1;i--){
      std::sort(floor[i].begin(),floor[i].end(),comp);
      Max[i]=Max[i+1]+size[floor[i][0]];
    }
    Dfs(1,0);
    printf("%d",n-pre::ans);
  }
}
int main(){
  freopen("epidemic.in","r",stdin);
  freopen("epidemic.out","w",stdout);
  mid :: Init();
  mid :: Work();
  return 0;
}
时间: 2024-08-26 04:25:28

[NOIP2003] 传染病控制 搜索+剪枝的相关文章

【搜索剪枝】HDU 5469 Antonidas

通道 题意:给出1字母树,询问一字符串是否出现在该树中 思路:直接搜索剪枝,有人点分治?写了几发都T了..有人会了教我? 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Edge { int v, nxt; Edge () { } Edge (int _v, int _n) { v = _v, nxt = _n; } }; const in

poj 1054 The Troublesome Frog (暴力搜索 + 剪枝优化)

题目链接 看到分类里是dp,结果想了半天,也没想出来,搜了一下题解,全是暴力! 不过剪枝很重要,下面我的代码 266ms. 题意: 在一个矩阵方格里面,青蛙在里面跳,但是青蛙每一步都是等长的跳, 从一个边界外,跳到了另一边的边界外,每跳一次对那个点进行标记. 现在给你很多青蛙跳过后的所标记的所有点,那请你从这些点里面找出 一条可能的路径里面出现过的标记点最多. 分析:先排序(目的是方便剪枝,break),然后枚举两个点,这两个 点代表这条路径的起始的两个点.然后是三个剪枝,下面有. 开始遍历时,

USACO/fence8 迭代加深搜索+剪枝

题目链接 迭代加深搜索思想. 枚举答案K,考虑到能否切出K个木头,那么我们当然选最小的K个来切. 1.对于原材料,我们是首选最大的还是最小的?显然,首选大的能够更容易切出,也更容易得到答案. 2.对于目标木头,我们是优先得到最大的还是最小的?显然,由于K个木头我们都要得到,那么当然先把最大的(最难得到的)先得到,这种搜索策略更优. 3.假设总原材料为all,前K个木头总和为sum,那么all-sum就是这一次切割过程中能[浪费]的最大数目.对于一个切剩下的原材料,若它比最小的目标木头还要小,则它

[NOIP2003] 传染病控制题解

问题 F: [NOIP2003] 传染病控制 时间限制: 1 Sec  内存限制: 128 MB 题目描述 [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府 决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群.于是,蓬莱国 的疾病控制中心决定采取切断传播途径的方法控制疾病传播.经过 WHO (世界卫生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径

hdu 5887 搜索+剪枝

Herbs Gathering Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 687    Accepted Submission(s): 145 Problem Description Collecting one's own plants for use as herbal medicines is perhaps one of t

poj 2531 搜索剪枝

Network Saboteur Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description A university network is composed of N computers. System administrators gathered informat

【迭代博弈+搜索+剪枝】poj-1568--Find the Winning Move

poj  1568:Find the Winning Move   [迭代博弈+搜索+剪枝] 题面省略... Input The input contains one or more test cases, followed by a line beginning with a dollar sign that signals the end of the file. Each test case begins with a line containing a question mark and

『生日蛋糕 搜索剪枝』

Description 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为N×π的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱.当i < M时,要求Ri > Ri+1且Hi > Hi+1. 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小. 令Q = S×π请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小.(除Q外,以上所

poj 1198 hdu 1401 搜索+剪枝 Solitaire

写到一半才发现可以用双向搜索4层来写,但已经不愿意改了,干脆暴搜+剪枝水过去算了. 想到一个很水的剪枝,h函数为  当前点到终点4个点的最短距离加起来除以2,因为最多一步走2格,然后在HDU上T了,又发现再搜索过程中,这个估价函数应该是递减的(贪心),再加上这个剪枝就过了. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<list> #