• 洛谷 P1041 传染病控制 题解


    这道题是一个错题,但是我还是做了。

    一开始我想的是一个贪心的做法,但是如果树含有一条很长的链就会hack掉这种做法,而数据范围并不大,所以就老老实实地写搜索。

    大体上是先搜索一遍整棵树,处理处每个点的父亲节点编号,子树大小和所在深度。

    然后需要把相同深度的点归到一起,因为对于每次搜索,可选择的都是同一层的点(本来是边,可以转换成点)。

    然后就是根据题意搜索:每次在同层的点中选一个切断。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define maxn 610
    #define int long long
    #define rep(i,s,e) for(register int i=s;i<=e;++i)
    #define dwn(i,s,e) for(register int i=s;i>=e;--i)
    using namespace std;
    inline int read()
    {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
        return f*x;
    }
    inline void write(int x)
    {
        if(x<0){putchar('-');x=-x;}
        if(x>9)write(x/10);
        putchar(x%10+'0');
    }
    vector<int> sd[maxn];
    int n,p,cnt,ans,maxdep;
    int head[maxn];
    int fa[maxn],siz[maxn],deep[maxn],tag[maxn];
    struct node
    {
        int v,nex;
    }edge[maxn];
    inline void add(int x,int y)
    {
        edge[++cnt].v=y;
        edge[cnt].nex=head[x];
        head[x]=cnt;
    }
    void pre_dfs(int now,int from,int dep)
    {
        fa[now]=from;
        siz[now]=1;
        deep[now]=dep;
        maxdep=max(maxdep,dep);
        for(int i=head[now];i;i=edge[i].nex)
        {
            int to=edge[i].v;
            if(to==from) continue;
            pre_dfs(to,now,dep+1);
            siz[now]+=siz[to];
        }
    }
    void dfs(int dep,int f)
    {
        if(dep==maxdep+1)
        {
            ans=min(ans,f);
            return;
        }
        for(int i=0;i<sd[dep].size();++i)
        {
            if(tag[fa[sd[dep][i]]]==1) tag[sd[dep][i]]=1;
            else tag[sd[dep][i]]=0;
        }
        bool flag=0;
        for(int i=0;i<sd[dep].size();++i)
        {
            if(tag[sd[dep][i]]==0) flag=1;
        }
        if(flag==0)
        {
            ans=min(ans,f);
            return;
        }
        for(int i=0;i<sd[dep].size();++i)
        {
            if(tag[sd[dep][i]]==1) continue;
            tag[sd[dep][i]]=1;
            dfs(dep+1,f-siz[sd[dep][i]]);
            tag[sd[dep][i]]=0;
        }
    }
    signed main()
    {
        n=read();p=read();
        ans=n;
        rep(i,1,p)
        {
            int x=read(),y=read();
            add(x,y);
            add(y,x);
        }
        pre_dfs(1,0,1);
        rep(i,1,n) sd[deep[i]].push_back(i);
        dfs(2,n);
        write(ans);
        return 0;
    }
  • 相关阅读:
    32位和64位系统区别及int字节数
    进程的三种状态及转换
    已知二叉树的前序/后序遍历和中序遍历,求后序/前序遍历
    一步一步写算法
    Ubuntu中APache+mod_pyhon
    JAVA SOCKET
    TCP连接 断开
    mfc 创建一个C++ 类
    mfc 类的析构函数
    mfc 类对象的引用
  • 原文地址:https://www.cnblogs.com/handsome-zyc/p/13646854.html
Copyright © 2020-2023  润新知