hdu 3586 树形dp+二分

题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线。现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit。1<=n<=1000,1<=m<=100万

链接:点我

题目要问的是最小的最大限制,必然二分答案
然后对于每一个值,树形DP判定是否可行
dp[i]表示要切断以i为根的其它所有子树的最小代价。
其中设定叶子结点的代价为无穷大
那么对于某一个非叶子结点,要切断一棵子树就有两种选择,切断以孩子为根的子树或者切断根与孩子的边。
如果根与孩子的边大于限制,那就取无穷大。
最后判断1号结点的总花费是否小于等于m
注意:无穷大不要取太大,否则会连续相加溢出

Sample Input
5 5
1 3 2
1 4 3
3 5 5
4 2 6
0 0
 

 

Sample Output
3

 注意没结果要输出-1

INF大小要注意搞好

 

 1 #include<cstdio>

 2 #include<iostream>

 3 #include<algorithm>

 4 #include<cstring>

 5 #include<cmath>

 6 #include<queue>

 7 #include<map>

 8 using namespace std;

 9 #define MOD 1000000007

10 const int INF=1000010;

11 const double eps=1e-5;

12 typedef long long ll;

13 #define cl(a) memset(a,0,sizeof(a))

14 #define ts printf("*****\n");

15 const int MAXN=1005;

16 int n,m,tt,tot=0,head[MAXN],dp[MAXN];

17 int maxw;

18 struct edge

19 {

20     int to,next;

21     int w;

22 }edge[MAXN*2];

23 void addedge(int a,int b,int w)

24 {

25     edge[tot].to=a;

26     edge[tot].next=head[b];

27     edge[tot].w=w;

28     head[b]=tot++;

29 }

30 void init()

31 {

32     memset(head,-1,sizeof(head));

33     tot=0;

34     maxw=0;

35 }

36 void dfs(int u,int pre,int limit)

37 {

38     int flag=0;

39     for(int i=head[u];i!=-1;i=edge[i].next)

40     {

41         int v=edge[i].to;

42         if(v==pre)  continue;

43         flag=1;

44         dfs(v,u,limit);

45         if(edge[i].w<=limit)    dp[u]+=min(dp[v],edge[i].w);    //切子树,或者切与子树相连的边

46         else    dp[u]+=dp[v];   //只能切断子树

47     }

48     if(!flag)   dp[u]=INF;  //叶子不能切哦

49 }

50 int main()

51 {

52     int i,j,k;

53     #ifndef ONLINE_JUDGE

54     freopen("1.in","r",stdin);

55     #endif

56     while(scanf("%d%d",&n,&m)!=EOF)

57     {

58         init();

59         if(n==0&&m==0)  break;

60         int u,v,w;

61         for(i=1;i<n;i++)

62         {

63             scanf("%d%d%d",&u,&v,&w);

64             addedge(u,v,w);

65             addedge(v,u,w);

66             if(maxw<w)  maxw=w;

67         }

68         int l=1,r=maxw;

69         int ans=-1;

70         while(l<=r)

71         {

72             cl(dp);

73             int mid=(l+r)>>1;

74             dfs(1,-1,mid);

75             if(dp[1]<=m)

76             {

77                 ans=mid;

78                 r=mid-1;

79             }

80             else    l=mid+1;

81         }

82         printf("%d\n",ans);

83     }

84 }

 

你可能感兴趣的:(HDU)