zoukankan      html  css  js  c++  java
  • BZOJ2525 [Poi2011]Dynamite 【二分 + 贪心】

    题目链接

    BZOJ2525

    题解

    就是要求所有有炸弹的点到点燃点距离最大值最小
    显然二分答案距离(D)
    然后按深度排序,贪心点燃当前没覆盖的深度最深的点往上第(D)层的点
    每覆盖一个点要标记其能到达的点
    显然暴力标记均摊是(O(n))
    复杂度(O(nlogn))

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 300005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int h[maxn],ne = 1;
    struct EDGE{int to,nxt;}ed[maxn << 1];
    inline void build(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    int n,m,tag[maxn],dep[maxn],fa[maxn],L,tot;
    int id[maxn],vis[maxn],ok[maxn],N;
    void dfs(int u){
    	Redge(u) if ((to = ed[k].to) != fa[u]){
    		fa[to] = u; dep[to] = dep[u] + 1;
    		dfs(to);
    	}
    }
    void Dfs(int u,int len,int pre){
    	ok[u] = true;
    	if (vis[u] >= len) return;
    	vis[u] = len;
    	if (!len) return;
    	Redge(u) if ((to = ed[k].to) != pre)
    		Dfs(to,len - 1,u);
    }
    bool check(int mid){
    	tot = 0; L = mid;
    	REP(i,n) vis[i] = ok[i] = 0;
    	REP(i,N){
    		int u = id[i],k;
    		if (!ok[u]){
    			k = L;
    			while (k-- && fa[u]) u = fa[u];
    			Dfs(u,L,0);
    			tot++;
    		}
    	}
    	return tot <= m;
    }
    inline bool cmp(const int& a,const int& b){
    	return dep[a] > dep[b];
    }
    int main(){
    	n = read(); m = read();
    	for (int i = 1; i <= n; i++){
    		tag[i] = read();
    		if (tag[i]) id[++N] = i;
    	}
    	for (int i = 1; i < n; i++) build(read(),read());
    	dfs(1);
    	sort(id + 1,id + 1 + N,cmp);
    	int l = 0,r = n,mid;
    	while (l < r){
    		mid = l + r >> 1;
    		if (check(mid)) r = mid;
    		else l = mid + 1;
    	}
    	printf("%d
    ",l);
    	return 0;
    }
    
    
  • 相关阅读:
    百度ECharts数据绑定诀窍
    SQL操作Json数据
    c# 如何得到一个字符的ASCII码
    Sql数据库收缩 语句特别快
    Hive中 使用 Round() 的坑
    [转]Hive 数据类型
    [转] Hive函数大全
    使用Hive Rest API 连接HDInsight
    Hive动态分区 参数配置及语法
    Js的引用赋值与传值赋值
  • 原文地址:https://www.cnblogs.com/Mychael/p/9234695.html
Copyright © 2011-2022 走看看