code1091 传染病控制

1.读入图,边是双向的

2.递归建树,同时确定每一层的节点

3.dfs按层搜索,先把这一层所有被传染的(die[pa[k]]=true的)的die置为true

然后循环,每次把一个die为true的变为false,表示断开这条边,继续dfs

dfs的最后记得把这一层die的全部置为false(查了一下午...)

退出条件:now当前死的人>=ans, f当前层>layerNum,num这一层死的人==0

 

代码:

#include<iostream>
#define Size 305
#define INF 10000000
using namespace std;

int n;
int g[Size][Size];
int layer[Size][Size];
int pa[Size];
bool vis[Size];
bool die[Size];
int ans=INF;
int layerNum=0;
int way[Size];

void buildTree(int k,int f){
    vis[k]=true;
    layer[f][++layer[f][0]]=k;
    if(f>layerNum)layerNum=f;
    
    for(int i=1;i<=g[k][0];i++){
        int s=g[k][i];
        if(!vis[s]){
            pa[s]=k;
            buildTree(s,f+1);
        }
    }
}

void dfs(int f,int now){//f:layer
    if(now>=ans)return;
    if(f>layerNum){
        ans=min(now,ans);
        /*cout<<ans<<": ";
        for(int i=1;i<=layerNum;i++)cout<<way[i]<<' ';
        cout<<endl;*/
        return;
    }
    int num=0;
    for(int i=1;i<=layer[f][0];i++){
        int k=layer[f][i];
        if(die[pa[k]])die[k]=true,num++;
    }
    if(num==0){
        ans=min(now,ans);
        return;
    }
    for(int i=1;i<=layer[f][0];i++){
        int k=layer[f][i];
        if(die[k]){
            way[f]=k;
            die[k]=false;
            dfs(f+1,now+num-1);
            die[k]=true;
        }
    }
    for(int i=1;i<=layer[f][0];i++){//退出之前清零当前层的die 
        die[layer[f][i]]=false;
    }
}

int main(){
    freopen("1091.in","r",stdin);
    
    int p,a,b;
    cin>>n>>p;
    for(int i=1;i<=p;i++){
        cin>>a>>b;
        g[a][++g[a][0]]=b;
        g[b][++g[b][0]]=a;
    }
    buildTree(1,1);
    /*for(int i=1;i<=layerNum;i++){
        for(int j=1;j<=layer[i][0];j++)
            cout<<layer[i][j]<<' ';
        cout<<endl;
    }*/
    die[1]=true;
    dfs(2,1);
    cout<<ans<<endl;
    
    fclose(stdin);
    return 0;
} 

 

posted @ 2016-06-19 20:02  FuTaimeng  阅读(181)  评论(0编辑  收藏  举报