luogu#P2016 战略游戏
Posted nent
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu#P2016 战略游戏相关的知识,希望对你有一定的参考价值。
题意:
给出一棵有 (N) 个节点的树,节点编号 (0) ~ (N-1) 。如果在一个节点上放置一个士兵,那么该节点及与该节点相连的所有节点都可以被瞭望到。求瞭望到所有节点所需的最少的士兵数。
解法:
树形dp
设 (f[i][j]) = 节点 (i) 选((j=1))不选((j=0))的最少需要的士兵
因为对于一个节点 (i) ,如果它不选,那么必须选与它相连的点的其中一个,则:
f[x][1]+=min(f[v][0],f[v][1]); //设v是与x相邻的点
f[x][0]+=f[v][1];
因为没有给出树根,所以要手动求出。
感觉跟没有舞会的上司差不多,居然还是一道蓝题
#include<iostream>
#define N 1505
using namespace std;
struct Edge{int next,to;}edge[N<<1];
int n_e,head[N],n,root;
int f[N][2];
bool rt[N];
void dp(int x);
void addedge(int from,int to);
void init();
int main()
{
init();
dp(root);
cout<<min(f[root][1],f[root][0]);
return 0;
}
void init()
{
cin>>n;
for(int i=0;i<n;i++)
{
int id,num,v;
cin>>id>>num;
f[i][1]=1;
for(int j=0;j<num;j++)
{
cin>>v;
rt[v]=1;
addedge(id,v);
}
}
for(int i=0;i<n;i++)
if(!rt[i])
{
root=i;
break;
}
}
void addedge(int from,int to)
{
edge[++n_e].next=head[from];
edge[n_e].to=to;
head[from]=n_e;
}
void dp(int x)
{
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
dp(v);
f[x][1]+=min(f[v][1],f[v][0]);
f[x][0]+=f[v][1];
}
}
以上是关于luogu#P2016 战略游戏的主要内容,如果未能解决你的问题,请参考以下文章
luogu P3345 [ZJOI2015]幻想乡战略游戏(点分树)
luogu P3345 [ZJOI2015]幻想乡战略游戏 |动态点分治