[题解]洛谷P1041 传染病控制

这道题的树没说明父亲和儿子的输入顺序,以前也遇到过,蛋疼

思路:

1)ans=总点数-隔离了的点数

2)第i次隔离的边一定是深度为i的点和深度为i-1的点的连边,所以用vector存每层的点

3)预处理f[i]储存以i为根的子树的点数

4)已经被隔离了的点就不用了搜惹

5)由于隔离了的点数是单调递增的,所以不用判断深度是否达到最大深度,直接在每一层结束时更新最大值(否则因为上面的剪枝,最后一层的点早已被隔离时,就统计不到惹)

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 310,MAXP = 310;
#define DEBUG(x) cout<< #x <<":"<< x <<endl

inline int read(){
    int x=0,w=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')w=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    return x*w;
}

int n,p;
int first[MAXN];

vector<int>node[MAXP];

struct edge{
    int u,v,next;
}e[MAXP*2];

int tot=0;
void insert(int u,int v){
    e[++tot].u=u;e[tot].v=v;e[tot].next=first[u];first[u]=tot;
}

int fa[MAXN],d[MAXN],f[MAXN],vis[MAXN]={0},deep=0;
void init(int x,int fat){
    f[x]=1;
    if(x!=1){
        d[x]=d[fat]+1;
        fa[x]=fat;
    }
    deep=max(d[x],deep);
    node[d[x]].push_back(x);
    for(int i=first[x];i!=-1;i=e[i].next){
        if(e[i].v!=fat){
            init(e[i].v,x);
            f[x]+=f[e[i].v];
        }
    }
}

void tag(int x,int num){
    vis[x]=num;
    for(int i=first[x];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v!=fa[x]){
            tag(v,num);
        }
    }
}

int ans=0;
void solve(int x,int o){
    for(int i=0;i<node[x].size();i++){
        int u=node[x][i];
        if(vis[u])continue;
        tag(u,1);
        solve(x+1,o+f[u]);
        tag(u,0);
    }
    ans=max(ans,o);
}

int main(){
    memset(first,-1,sizeof(first));
    n=read();p=read();
    for(int i=1;i<=p;i++){
        int u=read(),v=read();
        insert(u,v);insert(v,u);
    }
    d[1]=0;
    init(1,-1);
    solve(1,0);
    printf("%d\n",n-ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sjrb/p/10403745.html
今日推荐