hdu3586 Information Disturbing
【题意】
给定一棵以1为根节点的有n个点的有边权的无向树,要求切断所有叶子节点和根节点的联系,要求边权和小于等于m,问最大的边权值最小为多少
【分析】
首先很显然,我们需要二分答案转换为判定性的问题,然后看通过<=mid的边权的边能否是总的边权小于等于m还满足条件
【代码】
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1005; int head[maxn],n,m; struct edge { int to,nxt,v; }e[maxn<<1]; int cnt; void add(int x,int y,int z) { e[++cnt].to=y; e[cnt].nxt=head[x]; e[cnt].v=z; head[x]=cnt; } const int inf=0x3f3f3f3f; ll f[maxn]; void dfs(int u,int fa,int lim) { int flag=0; f[u]=0; for(int i=head[u];i;i=e[i].nxt) { int to=e[i].to; if(to==fa) continue; flag++; dfs(to,u,lim); if(e[i].v>lim) f[u]+=f[to]; else f[u]+=min(f[to],1ll*e[i].v); } if(!flag) f[u]=inf; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); while(scanf("%d%d",&n,&m) && n+m) { int x,y,z,maxi=0; memset(head,0,sizeof(head)); cnt=0; for(int i=2;i<=n;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); maxi=max(maxi,z); } // printf("%d\n",maxi); int l=1,r=maxi,ans=-1; while(l<=r) { int mid=(l+r)>>1; dfs(1,0,mid); // for(int i=1;i<=n;i++) printf("%d ",f[i]); if(f[1]<=m) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); } return 0; }
这里这个f开long long 的原因是inf加了很多次会爆int,开始wa了好多次 qwq