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

BZOJ 2314: 士兵的放置( 树形dp )

时间:2015-11-20 19:59:59      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

树形dp...

dp(x, 0)表示结点x不放士兵, 由父亲控制;

dp(x, 1)表示结点x不放士兵, 由儿子控制;

dp(x, 2)表示结点x放士兵. 

-------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
 
const int maxn = 500009;
const int MOD = 1032992941;
 
struct edge {
int to;
edge* next;
} E[maxn << 1], *pt = E, *head[maxn];
 
void AddEdge(int u, int v) {
pt->to = v; pt->next = head[u]; head[u] = pt++;
}
 
void upd0(ll &x, int t) {
if((x += t) >= MOD) x -= MOD;
}
 
void upd1(ll &x, int t) {
x = x * t % MOD;
}
 
int N;
ll dp[maxn][3], cnt[maxn][3];
 
void init() {
scanf("%d", &N);
for(int i = 1; i < N; i++) {
int u, v;
scanf("%d%d", &u, &v);
AddEdge(--u, --v);
AddEdge(v, u);
}
}
 
void dfs(int x, int fa) {
dp[x][0] = 0; dp[x][1] = maxn; dp[x][2] = 1;
cnt[x][0] = cnt[x][1] = cnt[x][2] = 1;
ll Min, sum;
for(edge* e = head[x]; e; e = e->next) if(e->to != fa) {
dfs(e->to, x);
Min = min(min(dp[e->to][0], dp[e->to][1]), dp[e->to][2]);
sum = 0;
dp[x][2] += Min;
for(int i = 0; i < 3; i++)
if(dp[e->to][i] == Min) upd0(sum, cnt[e->to][i]);
upd1(cnt[x][2], sum);
Min = min(dp[x][1] + min(dp[e->to][1], dp[e->to][2]), dp[x][0] + dp[e->to][2]);
sum = 0;
for(int i = 1; i < 3; i++) 
if(dp[x][1] + dp[e->to][i] == Min) upd0(sum, cnt[e->to][i]);
upd1(cnt[x][1], sum);
if(dp[x][0] + dp[e->to][2] == Min)
upd0(cnt[x][1], ll(cnt[x][0]) * cnt[e->to][2] % MOD);
dp[x][1] = Min;
dp[x][0] += dp[e->to][1];
upd1(cnt[x][0], cnt[e->to][1]);
}
}
 
int main() {
init();
dfs(0, -1);
ll ans = min(dp[0][1], dp[0][2]), sum = 0;
for(int i = 1; i < 3; i++)
if(dp[0][i] == ans) upd0(sum, cnt[0][i]);
printf("%lld\n%lld\n", ans, sum);
return 0;
}

-------------------------------------------------------------------------------------

2314: 士兵的放置

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 114  Solved: 31
[Submit][Status][Discuss]

Description


八中有N个房间和N-1双向通道,任意两个房间均可到达.现在出了一件极BT的事,就是八中开始闹鬼了。老大决定加强安保,现在如果在某个房间中放一个士兵,则这个房间以及所有与这个房间相连的房间都会被控制.现在

老大想知道至少要多少士兵可以控制所有房间.以及有多少种不同的方案数. 

Input

 

第一行一个数字N,代表有N个房间,房间编号从1开始到N.N<=500000,下面将有N-1行,每行两个数,代表这两个房间相连. 

Output

第一行输出至少有多少个士兵才可以控制所有房间第二行输出有多少种方案数,方案数会比较大,输出除以1032992941的余数吧. 

Sample Input

6
1 2
1 3
1 5
1 4
5 6

Sample Output

2
2


HINT

第一种方案是将士兵放在1号房间及6号房间 

第二种方案是将士兵放在1号房间及5号房间 

Source

 

BZOJ 2314: 士兵的放置( 树形dp )

标签:

原文地址:http://www.cnblogs.com/JSZX11556/p/4981732.html

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