規劃 洛谷p1642
阿新 • • 發佈:2018-11-01
題目描述
某地方有N個工廠,有N-1條路連線它們,且它們兩兩都可達。每個工廠都有一個產量值和一個汙染值。現在工廠要進行規劃,拆除其中的M個工廠,使得剩下的工廠依然連成一片且 總產量/總汙染 的值最大。
輸入輸出格式
輸入格式:
第一行N M(1<N<100,1<=M<N),表示工廠個數和要拆除的個數。
第二行N個正整數,表示每個工廠的產值[1..10000]
第三行N個正整數,表示每個工廠的汙染值[1..10000]
接著N-1行,每行兩個正整數a b(1<=a,b<=N)表示a,b之間相連。
輸出格式:
總產量/總汙染 的最大值,保留一位小數。
輸入輸出樣例
輸入樣例#1: 複製
3 2 2 3 4 1 1 1 1 2 2 3
輸出樣例#1: 複製
4.0
題解:01分數規劃二分答案,樹形dp求包含(n-m)個節點的最大子樹和。
#include<bits/stdc++.h> #define f(i,l,r) for(i=(l);i<=(r);i++) #define ff(i,r,l) for(i=(r);i>=(l);i--) using namespace std; const int MAXN=105,INF=1e20; double EPS=1e-3; struct Node{ int v,w; double c; }a[MAXN]; struct Edge{ int v,nxt; }e[MAXN<<1]; int n,m; double f[MAXN][MAXN]; int h[MAXN],tot,size[MAXN],flag; inline void add(int u,int v) { e[tot].v=v; e[tot].nxt=h[u]; h[u]=tot++; } void dfs(int u,int fa) { int i,j,k; size[u]=1; f[u][1]=a[u].c; for(i=h[u];~i;i=e[i].nxt){ int v=e[i].v; if(v==fa) continue; dfs(v,u); if(flag) return; size[u]+=size[v]; int max_j=min(n-m,size[u]); ff(j,max_j,2){ f(k,1,j-1){ f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); } } } if(f[u][n-m]>=0){ flag=1; } } bool check(double ans) { int i,j; f(i,1,n){ a[i].c=1.0*a[i].v-ans*a[i].w; } f(i,1,n){ f(j,1,n){ f[i][j]=-INF; } } flag=0; dfs(1,-1); return flag; } int main() { ios::sync_with_stdio(false); memset(h,-1,sizeof(h)); int i,j,u,v; double l=0,r=10000; cin>>n>>m; f(i,1,n){ cin>>a[i].v; } f(i,1,n){ cin>>a[i].w; } f(i,1,n-1){ cin>>u>>v; add(u,v); add(v,u); } while(r-l>EPS){ double mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } cout<<fixed<<setprecision(1)<<l<<endl; return 0; }