zoukankan      html  css  js  c++  java
  • 洛谷1041 传染病控制

    洛谷1041 传染病控制


    原题链接


    交题记录

    16:52 20'
    不知道是双向边。。。
    16:54 70'
    vector忘记判断size了。。。
    16:59 80'
    sum忘特判1了。。。
    17:00 90'
    sum忘特判0了。。。还能说什么
    17:02 AC
    呵呵呵。。。
    17:05 AC第二次
    把vector换掉了。


    题解

    我太弱了。。。
    这题我只会dfs乱搞
    但好像没人用树状数组优化。。。
    先把dfn,siz都搞出来
    一个点的子树在树状数组中就对应([dfn,dfn+siz))
    割掉这个点时把这棵子树都标记为1,回溯再标记为0,(O(log_2siz))
    每次搜索把树状数组中标记为0的点数记为(sum),下一个搜索就得多感染(sum-1)人,然后枚举点割掉就行了


    Code

    vector版本

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define Fname "epidemic"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=310,maxm=maxn<<1;
    int fir[maxn],nxt[maxm],dis[maxm];
    int siz[maxn],dfn[maxn],ans=1e9,n;
    vector<int>s[maxn];
    il vd DFS(int now,int dep=1,int fa=-1){
        s[dep].push_back(now);
        siz[now]=1,dfn[now]=++dfn[0];
        erep(i,now)if(dis[i]^fa)DFS(dis[i],dep+1,now),siz[now]+=siz[dis[i]];
    }
    int tree[maxn];
    il vd add(int p,int k){while(p<=n)tree[p]+=k,p+=p&-p;}
    il int summ(int p){int ret=0;while(p)ret+=tree[p],p-=p&-p;return ret;}
    il vd dfs(int now,int gg){
        if(gg>=ans)return;
        if(s[now].size()==0){ans=gg;return;}
        int sum=0;
        rep(i,0,s[now].size()-1)if(!summ(dfn[s[now][i]]))++sum;
        if(gg+sum-1>=ans)return;
        if(sum==1||sum==0){ans=min(ans,gg);return;}
        rep(i,0,s[now].size()-1)if(!summ(dfn[s[now][i]])){
    	add(dfn[s[now][i]],1);
    	add(dfn[s[now][i]]+siz[s[now][i]],-1);
    	dfs(now+1,gg+sum-1);
    	add(dfn[s[now][i]],-1);
    	add(dfn[s[now][i]]+siz[s[now][i]],1);
        }
    }
    int main(){
        freopen(Fname".in","r",stdin);
        freopen(Fname".out","w",stdout);
        n=gi();
        int m=gi(),id=0;
        rep(i,1,m){
    	int a=gi(),b=gi();
    	nxt[++id]=fir[a],fir[a]=id,dis[id]=b;
    	nxt[++id]=fir[b],fir[b]=id,dis[id]=a;
        }
        DFS(1);
        dfs(2,1);
        printf("%d
    ",ans);
        return 0;
    }
    

    没有vector(开O2会吃亏)

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define Fname "epidemic"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=310,maxm=maxn<<1;
    int fir[maxn],nxt[maxm],dis[maxm];
    int siz[maxn],dfn[maxn],k[maxn],s[maxn][maxn],ans=1e9,n;
    il vd DFS(int now,int dep=1,int fa=-1){
        s[dep][++k[dep]]=now;
        siz[now]=1,dfn[now]=++dfn[0];
        erep(i,now)if(dis[i]^fa)DFS(dis[i],dep+1,now),siz[now]+=siz[dis[i]];
    }
    int tree[maxn];
    il vd add(int p,int k){while(p<=n)tree[p]+=k,p+=p&-p;}
    il int summ(int p){int ret=0;while(p)ret+=tree[p],p-=p&-p;return ret;}
    il vd dfs(int now,int gg){
        if(gg>=ans)return;
        if(!k[now]){ans=gg;return;}
        int sum=0;
        rep(i,1,k[now])if(!summ(dfn[s[now][i]]))++sum;
        if(gg+sum-1>=ans)return;
        if(sum==1||sum==0){ans=min(ans,gg);return;}
        rep(i,1,k[now])if(!summ(dfn[s[now][i]])){
    	add(dfn[s[now][i]],1);
    	add(dfn[s[now][i]]+siz[s[now][i]],-1);
    	dfs(now+1,gg+sum-1);
    	add(dfn[s[now][i]],-1);
    	add(dfn[s[now][i]]+siz[s[now][i]],1);
        }
    }
    int main(){
        freopen(Fname".in","r",stdin);
        freopen(Fname".out","w",stdout);
        n=gi();
        int m=gi(),id=0;
        rep(i,1,m){
    	int a=gi(),b=gi();
    	nxt[++id]=fir[a],fir[a]=id,dis[id]=b;
    	nxt[++id]=fir[b],fir[b]=id,dis[id]=a;
        }
        DFS(1);
        dfs(2,1);
        printf("%d
    ",ans);
        return 0;
    }
    

    给出两组数据

    In
    15 14
    2 1
    3 2
    4 2
    5 2
    6 1
    7 6
    8 6
    9 6
    10 1
    11 10
    12 10
    13 12
    14 10
    15 14
    Out
    8
    In
    
    
    100 99
    2 1
    3 2
    4 3
    5 3
    6 3
    7 2
    8 7
    9 7
    10 9
    11 7
    12 2
    13 12
    14 12
    15 12
    16 2
    17 16
    18 17
    19 17
    20 16
    21 2
    22 21
    23 21
    24 21
    25 1
    26 25
    27 26
    28 25
    29 28
    30 25
    31 30
    32 31
    33 31
    34 31
    35 30
    36 35
    37 35
    38 37
    39 37
    40 1
    41 40
    42 41
    43 41
    44 41
    45 41
    46 40
    47 46
    48 40
    49 40
    50 49
    51 40
    52 51
    53 51
    54 40
    55 54
    56 54
    57 1
    58 57
    59 58
    60 58
    61 58
    62 57
    63 62
    64 62
    65 62
    66 57
    67 66
    68 66
    69 66
    70 66
    71 57
    72 71
    73 71
    74 71
    75 74
    76 57
    77 76
    78 76
    79 76
    80 76
    81 1
    82 81
    83 82
    84 83
    85 82
    86 85
    87 81
    88 87
    89 88
    90 88
    91 87
    92 87
    93 92
    94 92
    95 94
    96 92
    97 96
    98 96
    99 92
    100 99
    Out
    55
    
    博主是蒟蒻,有问题请指出,谢谢!
    本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
  • 相关阅读:
    Linux下面编译安装ffmpeg
    Fidder简单使用方法(HTTPS抓取和url替换)
    关于一下个阶段的计划
    JAVA的随机的字符串的封装(基本上够用了)
    Shell Script中的间接变量引用
    进程概念
    int main(int argc, char *argv[])的解读
    存储数组数据到SharedPreferences
    C语言中的基本声明
    C中关于指针数组的用法
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7435871.html
Copyright © 2011-2022 走看看