【题目描述】
太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
【输入】
输入中数据描述一棵树,描述如下:第一行n,表示树中结点的数目。
第二行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i0
【输出】
输出最少的经费
#include
using namespace std;
const int maxn = 1000;
int pre[maxn];//存储父节点
bool visit[maxn];//DFS标记数组
int newpos[maxn];//遍历序列
int now;
int n, m;
int head[maxn];//链式前向星
struct Node {
int to; int next;};
Node edge[maxn];
void DFS(int x) {
newpos[now ++] = x;//记录遍历序列
for(int k = head[x]; k != -1; k = edge[k].next) {
if(!visit[ edge[k].to ]) {
visit[ edge[k].to ] = true;
pre[edge[k].to] = x;//记录父节点
DFS(edge[k].to);
}
}
}
int MDS() {
bool s[maxn] = {
0};
bool set[maxn] = {
0};
int ans = 0;
for(int i = n - 1; i >= 0; i--) {
//逆序进行贪心
int t = newpos[i];
if(!s[t]) {
//如果当前点没被覆盖
if(! set[ pre[t] ]) {
//当前点的父节点不属于支配集
set[ pre[t] ] = true;//当前点的父节点加入支配集
ans ++; //支配集节点个数加 1
}
s[t] = true; //标记当前点已被覆盖
s[ pre[t] ] = true;// 标记当前点的父节点被覆盖
s[ pre[ pre[t] ] ] = true;//标记当前点的父节点的父节点被覆盖
}
}
return ans;
}
int main() {
/* read Graph message*/ //建图
memset(visit, false, sizeof(visit));//初始化
now = 0;
visit[1] = true;
pre[1] = 1;
DFS(1);//从根节点开始寻摘遍历序列
MDS();
return 0;
}
//如果当前节点 被父节点来看守的话 那么 在u这个节点 无论是否有收尾都行,所以dp[u][0] 从 dp[v][1]、 dp[v][2] 两者小的那个状态转移
dp[u][0] += min(dp[v][1], dp[v][2]);
//如果当前节点 u这个点,我们自己放置一个守卫来看守, 那么可以从dp[v][0]、dp[v][1]、 dp[v][2] 中之最小的那个状态进行转移
dp[u][2] += Min(dp[v][0], dp[v][1], dp[v][2]);
//sum 的值为所有子节点vi 的min(dp[vi][1], dp[vi][2])的之和
sum += min(dp[v][1], dp[v][2]);
//如果u由子节点为v来看守,由于u有多个子节点v1、v2...vm,我们可以依次指定让子节点v来看守,其它节子点(设为vi 并且 vi != x)是否有看守都无所谓(因此从这些子节点的转移的状态是:min(dp[vi][1], dp[vii][2]),因为我们已经指定了当前v节点必须来看守u,那从v节点进行的状态转移必须是:dp[v][2],
dp[u][1] = min(dp[u][1], sum - min(dp[v][1], dp[v][2]) + dp[v][2]);
#include
#include
#include
#include
#include
#include
#include
#include
/* #include */
#include
#include
void fre() {
system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() {
system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
#define size() size() * 1LL
#define mod (ll)(10007)
#define Min(a, b, c) min(a, min(b, c))
#define Max(a, b, c) max(a, max(b, c))
using namespace std;
const int mxn = 2e3;
vector<int> e[mxn];
int w[mxn];
int dp[mxn][3];
void dfs(int u, int p)
{
dp[u][2] = w[u];
int sum = 0;
for_(i, 0, e[u].size() - 1)
{
int v = e[u][i];
if(v == p) continue;
dfs(v, u);
dp[u][0] += min(dp[v][1], dp[v][2]);
dp[u][2] += Min(dp[v][0], dp[v][1], dp[v][2]);
sum += min(dp[v][1], dp[v][2]);
}
dp[u][1] = INF;
for_(i, 0, e[u].size() - 1)
{
int v = e[u][i];
if(v == p) continue;
dp[u][1] = min(dp[u][1], sum - min(dp[v][1], dp[v][2]) + dp[v][2]);
}
}
int main()
{
/* fre(); */
int n; sd(n);
int u, x, t, v;
for_(i, 1, n)
{
sc("%d %d %d", &u, &x, &t);
w[u] = x;
for_(j, 1, t)
{
sd(v);
e[u].pb(v);
e[v].pb(u);
}
}
dfs(1, 0);
pr("%d\n", min(dp[1][1], dp[1][2]));
return 0;
}