AC日记——传染病控制 洛谷 P1041

传染病控制

思路:

  题目想问的是:

    有一棵树;

    对于除1外每个深度可以剪掉一棵子树;

    问最后剩下多少节点;

  题目意思一简单,这个题立马就变水了;

  搜索就能ac;

  数据有为链的情况,按深度为层次搜索的话要记得提前记录答案并return;

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 305
#define maxm 90005
#define INF 0x7fffffff

int n,m,head[maxn],E[maxm],V[maxm],cnt,ans=INF,dep[maxn];
int l[maxn],r[maxn],size[maxn],map[maxn][maxn],deepest;

bool if_[maxn];

inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}

inline void edge_add(int u,int v)
{
    E[++cnt]=head[u],V[cnt]=v,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,head[v]=cnt;
}

void pre(int now,int fa,int deep)
{
    deepest=max(deep,deepest),dep[now]=deep;
    map[deep][++size[deep]]=now,l[now]=++cnt;
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        pre(V[i],now,deep+1);
    }
    r[now]=cnt;
}

void dfs(int now,int ans_)
{
    if(ans_>=ans) return ;
    if(now==deepest)
    {
        ans=ans_;
        return ;
    }
    int pos=-1;
    for(int i=1;i<=size[now+1];i++) if(!if_[l[map[now+1][i]]]) pos++;
    if(pos==-1)
    {
        ans=min(ans,ans_);
        return ;
    }
    for(int v=1;v<=size[now];v++)
    {
        if(if_[l[map[now][v]]]) continue;
        for(int i=head[map[now][v]];i;i=E[i])
        {
            if(dep[V[i]]>dep[now]&&!if_[l[V[i]]])
            {
                for(int j=l[V[i]];j<=r[V[i]];j++) if_[j]=true;
                dfs(now+1,ans_+pos);
                for(int j=l[V[i]];j<=r[V[i]];j++) if_[j]=false;
            }
        }
    }
}

int main()
{
    in(n),in(m);int u,v;
    while(m--)
    {
        in(u),in(v);
        edge_add(u,v);
    }
    cnt=0,pre(1,0,1),dfs(1,1);
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6757892.html