zoukankan      html  css  js  c++  java
  • BZOJ1117 [POI2009]救火站Gas 贪心

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1117.html

    题目传送门 - BZOJ1117

    题意

      给你一棵树,现在要建立一些消防站,有以下要求:

        1. 消防站要建立在节点上,每个节点可能建立不只一个消防站。

        2. 每个节点应该被一个消防站管理,这个消防站不一定建立在该节点上。

        3. 每个消防站可以管理至多s个节点。

        4. 消防站只能管理距离(两点间最短路径的边数)不超过k的结点。

      请问至少要设立多少个消防站。

    题解

      考虑贪心从下往上走。

      设 rem[x][i] 表示 x 的子树中与 x 的距离为 i 的未决策节点总数。

      设 foc[x][i] 表示 x 的子树中与 x 的距离为 i 的灭火器还能管辖多少节点。

      贪心策略就是尽量把灭火器往祖先上应用。

      分两个情况再描述一下:

      1. 对于 rem[x][k] 这一部分,我们需要在节点 x 新增灭火器。

      2. i 从小到大检验 foc[x][i] ,如果它可以灭 rem[x][i] 或者 rem[x][i-1] ,那么必然灭了最好,否则到上面了就灭不了了;就算别的灭火器灭了它,我们只需要交换这两个灭火器的消灭对象就可以打到至少不劣的效果。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=100005,K=25;
    int read(){
    	int x=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;	
    }
    struct Graph{
    	static const int M=N*2;
    	int cnt,y[M],nxt[M],fst[N];
    	void clear(){
    		cnt=1;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int n,s,k;
    LL rem[N][K],foc[N][K];
    int ans=0;
    void solve(int x,int pre){
    	rem[x][0]++;
    	for (int i=g.fst[x];i;i=g.nxt[i])
    		if (g.y[i]!=pre){
    			int y=g.y[i];
    			solve(y,x);
    			for (int j=0;j<k;j++){
    				rem[x][j+1]+=rem[y][j];
    				foc[x][j]+=foc[y][j+1];
    			}
    		}
    	int d=(rem[x][k]+s-1)/s;
    	ans+=d;
    	foc[x][k]+=d*s;
    	for (int i=0;i<=k;i++)
    		for (int j=i;foc[x][i]&&j>=0&&(j>=i-1||x==1);j--){
    			d=min(foc[x][i],rem[x][j]);
    			foc[x][i]-=d;
    			rem[x][j]-=d;
    		}
    }
    int main(){
    	n=read(),s=read(),k=read();
    	g.clear();
    	for (int i=1;i<n;i++){
    		int a=read(),b=read();
    		g.add(a,b);
    		g.add(b,a);
    	}
    	solve(1,0);
    	int t=0;
    	for (int i=0;i<=k;i++)
    		t+=rem[1][i];
    	printf("%d
    ",ans+(t+s-1)/s);
    	return 0;
    }
    

      

  • 相关阅读:
    python使用ORM之如何调用多对多关系
    ORM
    初学者用pycharm创建一个django项目和一个app时需要注意的事项
    CSRF verification failed. Request aborted.
    函数三生成器
    函数二函数进阶二
    函数二函数进阶
    函数一函数初识
    文件操作初识
    类型与运算五
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1117.html
Copyright © 2011-2022 走看看