标签:
题意:
n个节点的通信连接树,切断每个边有一定的花费,要你切断边,在总花费不超过m的前提,使所有的其他节点都不能和节点1(根)连通,切边时有花费上限,让你最小化这个上限。
分析:最小化最大值,想到二分,二分上限求符合条件的总花费和m比较。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF=1<<20; const int mod = 1000000007; struct edge{ int t,w; }; vector<edge>e[1010]; int dp[1010],n,m,used[1010]; void dfs(int root,int limit){ used[root]=1; int f=0,tmp=0; for(int i=0;i<e[root].size();++i){ edge d=e[root][i]; int son=d.t; int c=d.w; if(used[son])continue; f=1; dfs(son,limit); if(c<=limit){ tmp+=min(dp[son],c);//小于上限,可切可不切 } else tmp+=dp[son];//大于上限不能切断 } if(f) dp[root]=tmp; else dp[root]=INF; } int main() { while(~scanf("%d%d",&n,&m)){ if(n==0&&m==0)break; int a; for(int i=1;i<=n;++i) e[i].clear(); for(int i=0;i<n-1;++i){ edge b; scanf("%d%d%d",&a,&b.t,&b.w); e[a].push_back(b); int tt=b.t; b.t=a; e[tt].push_back(b); } int l=0,r=m,ff=-1; while(l<=r){ memset(dp,0,sizeof(dp)); memset(used,0,sizeof(used)); int mid=(l+r)>>1; dfs(1,mid); if(dp[1]<=m){r=mid-1;ff=mid;} else l=mid+1; } printf("%d\n",ff); } return 0; }
HDU 3586-Information Disturbing(树形dp)
标签:
原文地址:http://www.cnblogs.com/zsf123/p/4698972.html