51nod 1378 夹克老爷的愤怒【贪心】

Description

夹克老爷逢三抽一之后,由于采用了新师爷的策略,乡民们叫苦不堪,开始组织起来暴力抗租。

夹克老爷很愤怒,他决定派家丁常驻村中进行镇压。

诺德县 有N个村庄,编号0 至 N-1,这些村庄之间用N - 1条道路连接起来。

家丁都是经过系统训练的暴力机器,每名家丁可以被派驻在一个村庄,并镇压当前村庄以及距离该村庄不超过K段道路的村庄。

夹克老爷一贯奉行最小成本最大利润的原则,请问要实现对全部村庄的武力控制,夹克老爷需要派出最少多少名家丁?

题解

如果数据是一条链的话,那么显然是从某一端开始扫,能不放就不放。现在变成了树,贪心自然就是从叶子结点往上扫,能不放就不放。那么,我们只要处理当前节点是否已经到了非放不可的地步,只要DFS的时候退一个值表示这个节点往上最多能控制多少节点(如果为负就表示包括自己有多少节点没被控制),判断一下一个节点的所有子节点中往上控制最多的能否控制最少的,类似的一些情况分类讨论一下就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100006
using namespace std;
inline char nc(){
    static char buf[100000],*i=buf,*j=buf;
    return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
    char ch=nc();int sum=0;
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum;
}
int n,K,tot,ans,lnk[maxn],nxt[maxn*2],son[maxn*2];
bool vis[maxn];
void add(int x,int y){
    nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot;
}
int dfs(int x){
    vis[x]=0;int M=0,m=1e9;bool c=1;
    for(int j=lnk[x];j;j=nxt[j]) if(vis[son[j]]){
        int t=dfs(son[j]);
        M=max(M,t);m=min(m,t);c=0;
    }
    if(c)m=0;
    if(M+m-1<0&&m==-K)return ans++,K;
    if(M+m-1<0&&!x)return ans++;
    if(M+m-1<0)return m-1;else return M-1;
}
int main(){
    freopen("lord.in","r",stdin);
    freopen("lord.out","w",stdout);
    n=_read();K=_read();
    for(int i=1,x,y;i<n;i++)x=_read(),y=_read(),add(x,y),add(y,x);
    memset(vis,1,sizeof(vis));
    dfs(0);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fyoier/article/details/78409012
今日推荐