太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
输入文件中数据表示一棵树,描述如下:
第1行 n,表示树中结点的数目。
第2行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(0对于一个n(0 < n<=1500)个结点的树,结点标号在1到n之间,且标号不重复。
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
输出文件仅包含一个数,为所求的最少的经费。
25
设 f [ i ] [ 0 ] f[i][0] f[i][0] 表示当前节点站士兵;
设 f [ i ] [ 2 ] f[i][2] f[i][2] 表示当前节点不站士兵,被父节点监视。
设 f [ i ] [ 1 ] f[i][1] f[i][1]表示当前节点不站士兵,被他其中一个子节点监视。
f[dep][0]+=min(f[a[i].to][0],min(f[a[i].to][1],f[a[i].to][2]));
}
f[dep][0]+=w[dep];//因为放了,所以最后要加上他的经费(在循环外)
for(int i=h[dep];i;i=a[i].next)
{
tmp[i]=min(f[a[i].to][1],f[a[i].to][0]);
tt+=tmp[i];
}
min(所有子节点可放可不放的和- 当前子节点可放可不放+当前子结点必须放(f[a[i].to][0]))
这个式子就可以求出当前子节点放士兵监视的值了
for(int i=h[dep];i;i=a[i].next)
f[dep][1]=min(tt-tmp[i]+f[a[i].x][0],f[dep][1]);
#include
#include
#include
#include
using namespace std;
typedef long long ll;//不开longlong见祖宗
ll n,h[10001],v[10001],f[10001][5],s[10001],ans,tot;
struct node
{
ll to,next;
}a[100001];
void add(ll x,ll y)
{
a[++tot]=(node){y,h[x]};
h[x]=tot;
}
void dp(ll k)
{
for(ll i=h[k];i>0;i=a[i].next)
{
ll y=a[i].to;
dp(y);
f[k][1]+=min(f[y][1],min(f[y][2],f[y][3]));
f[k][3]+=f[y][2];
}
f[k][1]+=s[k];
ll t=0;
for(ll i=h[k];i>0;i=a[i].next)
{
ll y=a[i].to;
t+=min(f[y][1],f[y][2]);
}
f[k][2]=0x7fffffff;
for(ll i=h[k];i>0;i=a[i].next)
{
ll y=a[i].to;
f[k][2]=min(f[k][2],t-min(f[y][1],f[y][2])+f[y][1]);
}
}
int main()
{
cin>>n;
for(ll i=1;i<=n;i++)
{
ll x,k;
cin>>x;
cin>>s[x]>>k;
for(ll j=1;j<=k;j++)
{
ll y;
cin>>y;
add(x,y);
v[y]=1;//用于判断根节点
}
}
for(ll i=1;i<=n;i++)
{
if(v[i]==0)
{
dp(i);
cout<<min(f[i][1],f[i][2]);
}
}
return 0;
}