码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P3942 将军令

时间:2019-09-26 21:43:54      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:tchar   src   view   stream   alt   set   赋值   cto   经验   

这是一类比较普遍的问题,即

给定一颗无权树,放置一个点可以覆盖距离它不超过k的节点(0 <= k <= n),问最少放置多少点可以将树上所有点全部覆盖

考虑贪心:

f[u][0] 距u最近的放置点到u距离 ; f[u][1] 距u最远的未覆盖点到u距离  

转移易得

f[u][0] = inf,f[u][1] = -inf;
f[u][0] = min(f[u][0],f[v][0] + 1);
f[u][1] = max(f[u][1],f[v][1] + 1);

考虑到:

    if(f[u][0] > k) f[u][1] = max(f[u][1],0); 
    if(f[u][0] + f[u][1] <= k) f[u][1] = -inf; 
    if(f[u][1] == k) ans++,f[u][0] = 0,f[u][1] = -inf; 

要赋值成-inf是要不对之后的转移产生影响(其实考虑定义也可以,但是这里不能随便用0

最后特判根d的f[1]是否有值即可

 

现在,考虑问题的加强版:

https://www.luogu.org/problem/P3523

只需记录is[i]代表i需要被覆盖,易得

    if(is[u] && f[u][0] > k) f[u][1] = max(f[u][1],0); 


三倍经验(滑稽

技术图片
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
#define O(x) cout << #x << " " << x << endl;
#define clr(a) memset(a,0,sizeof(a));
#define B cout << "breakpoint" << endl;
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
inline int read() {
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < 0 || ch > 9) {
        if(ch == -) op = -1;
        ch = getchar(); 
    }
    while(ch >= 0 && ch <= 9) {
        (ans *= 10) += ch - 0;
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 3e5 + 5;
const int inf = 99999999;
struct egde
{
    int to,next;
}e[maxn << 1];
int fir[maxn],alloc;
void adde(int u,int v)
{
    e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v;
    swap(u,v);
    e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v;
}
int f[maxn][2];
int n,m,ans,k;
 // f[u][0] 距u最近的放置点到u距离 ; f[u][1] 距u最远的未放置点到u距离  
bool is[maxn];
void dfs(int u,int fa)
{
    f[u][0] = inf,f[u][1] = -inf;
    for(int i = fir[u];i;i = e[i].next)
    {
        int v = e[i].to; if(v == fa) continue; 
        dfs(v,u); 
        f[u][0] = min(f[u][0],f[v][0] + 1);
        f[u][1] = max(f[u][1],f[v][1] + 1);
    }
    if(is[u] && f[u][0] > k) f[u][1] = max(f[u][1],0); 
    if(f[u][0] + f[u][1] <= k) f[u][1] = -inf; 
    if(f[u][1] == k) ans++,f[u][0] = 0,f[u][1] = -inf; 
}
int main()
{
    n = read(); k = 2;
    for(int i = 2;i <= n;i++)
    {
        int u = read();
        adde(u,i);
    }
    /*if(k == 0)
    {
        printf("%d",n);
        return 0;
    }*/
    for(int i = 1;i <= n;i++) is[i] = 1; 
    dfs(1,0);
    if(f[1][1] >= 0) ans++;
    printf("%d",ans); 
}
/*
6 0 0 
1 2 
1 3 
1 4 
4 5 
4 6
*/
View Code

 

Luogu P3942 将军令

标签:tchar   src   view   stream   alt   set   赋值   cto   经验   

原文地址:https://www.cnblogs.com/LM-LBG/p/11594009.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!