您的位置:首页 > 其它

HDU 3586【树形DP+二分】

2011-09-22 18:59 381 查看
题目:Information Disturbing

题意:

给出一棵树,和每条边的cost值,设置一个界限,要求切断所有叶子结点,切断的边的cost不能超过界限值,并且切断的边的总和不能超过m,求出这个最小界限值。

解题思路:

很明显的一道树型DP,DP[v],表示切断根结点的v的子树的最小花费,那么这个界限怎么处理呢,由于界限值范围要比总和m小得多,才1-1000,可以用二分枚举,这样在选择切边时可以根据这个枚举值进行判断处理。每个结点v,设其儿子结点为x1,x2,x3...则DP[v] = Min{DP[x1],Node[x1].cost} + Min{DP[x2], Node[x2].cost} + ...,当然,要判断Node[x].cost是否小于枚举的界限,Node[x].cost表示边(v,x)的cost值。

View Code

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;

const int MAX = 1000 + 10;
const int INF = 1001;
const int MAXM = 1000000 + 10;
struct TTree
{
int node, cost, next;
}Tree[MAX * 4];

int Pos[MAX];
int EdgeNumber;
int DP[MAX];
void init(int n)
{
EdgeNumber = n;
for(int i = 1; i <= n; ++i)
{
Pos[i] = i;
Tree[i].next = 0;
}
}
void addEdge(int from, int to, int cost)
{
++EdgeNumber;
Tree[Pos[from]].next = EdgeNumber;
Tree[Pos[from] = EdgeNumber].node = to;
Tree[EdgeNumber].cost = cost;
Tree[EdgeNumber].next = 0;
}

void dfs(int father, int node, int upper)
{
int sum = 0;
for(int ix = Tree[node].next; ix != 0; ix = Tree[ix].next)
{
if(Tree[ix].node != father)
{
dfs(node, Tree[ix].node, upper);
if(Tree[ix].cost <= upper && Tree[ix].cost < DP[Tree[ix].node])
{
sum += Tree[ix].cost;
}
else
sum += DP[Tree[ix].node];
}
}
if(sum == 0)
sum = MAXM;
DP[node] = sum;
}

int solve(int maxSum)
{
int left = 1, right = INF;
int mid;
while(left < right)
{
mid = (left + right) >> 1;
dfs(-1, 1, mid);
if(DP[1] <= maxSum)
right = mid;
else
left = mid + 1;
}
return left;
}
int main()
{
freopen("in.txt","r",stdin);
int n, m;
int x, y, c;
while(scanf("%d%d", &n, &m) == 2 && (n || m))
{
init(n);
for(int i = 1; i <= n - 1; ++i)
{
scanf("%d%d%d", &x, &y, &c);
addEdge(x, y, c);
addEdge(y, x, c);
}
int ans = solve(m);
if(ans >= INF)
printf("-1\n");
else
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: