noip 2003 传染病控制(历史遗留问题2333)

/*codevs 1091 搜索 几个月之前写的70分 今天又写了一遍 并且找到了错误 */
#include<cstdio>
#include<vector>
#define maxn 310
using namespace std;
int n,m,num,head[maxn],fa[maxn],ans=0x7fffffff,f[maxn];
vector<int>G[maxn],Son[maxn];
struct node{
    int v,pre;
}e[maxn*2];
void Add(int from,int to){
    num++;e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
void Build(int now,int from,int dep){
    G[dep].push_back(now);fa[now]=from;
    for(int i=head[now];i;i=e[i].pre){
        int v=e[i].v;
        if(v!=from){
            Son[now].push_back(v);
            Build(v,now,dep+1);
        }
    }
}
void Dfs(int c,int sum){//当前深度 已经挂掉几个 
    int num=0;
    if(sum>=ans)return;
    for(int i=0;i<G[c].size();i++){
        int x=G[c][i];
        if(f[x]==0)num++;//会挂掉的人数 
    }
    if(num==0){//没有人会挂掉 停止搜索 
        ans=min(ans,sum);return;
    }
    for(int i=0;i<G[c].size();i++){
        int x=G[c][i];
        if(f[x]){
            for(int k=0;k<Son[x].size();k++)
                f[Son[x][k]]=1; 
        }
    }
    for(int i=0;i<G[c].size();i++){
        int x=G[c][i];if(f[x])continue;
        for(int k=0;k<Son[x].size();k++)
            f[Son[x][k]]=1;
        f[x]=1;Dfs(c+1,sum+num-1);f[x]=0;
        for(int k=0;k<Son[x].size();k++)
            f[Son[x][k]]=0;
    }
    for(int i=0;i<G[c].size();i++){//回溯 回溯 回溯 要 彻底 
        int x=G[c][i];
        if(f[x]){
            for(int k=0;k<Son[x].size();k++)
                f[Son[x][k]]=0;
        }
    }
    
}
int main()
{
    freopen("epidemic.in","r",stdin);
    freopen("epidemic.out","w",stdout);
    scanf("%d%d",&n,&m);
    int u,v;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        Add(u,v);Add(v,u);
    }
    Build(1,0,0);Dfs(1,1);
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5994148.html