zoukankan      html  css  js  c++  java
  • [题解]洛谷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-ans);
        return 0;
    }
    本篇文章为SHINE_GEEK原创,转载请注明来源!
    written_by:SHINE_GEEK

    -------------------------------------
    签名:自己选的路,跪着也要走完;理想的实现,需要不懈奋斗!
    -------------------------------------
  • 相关阅读:
    .net事件和委托
    DataFormatString使用笔记
    DropDownList 绑定 枚举 Enum
    iOS开发如何实现消息推送机制
    JQuery调用asp.net后台方法
    Android 服务器推送技术
    Jquery Ajax ashx DataTable 传参 获取参数 C#
    jquery 基础
    [Perl书籍合集]Perl eBooks Collection
    LISP之根源
  • 原文地址:https://www.cnblogs.com/sjrb/p/10403745.html
Copyright © 2011-2022 走看看