bzoj 4472: [Jsoi2015]salesman【樹形dp+貪心】
阿新 • • 發佈:2018-11-09
一個點,設f[u]為要取最大值顯然是前最大停留次數-1個兒子的正數f和,排個序貪心即可
判重的話就是看沒選的裡面是否有和選了的裡面f值相同的,有的話就是一。注意在選的時候要把加進f的兒子的g合併上去
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=100005; int n,a[N],b[N],h[N],cnt,c[N],tot,f[N],g[N]; struct qwe { int ne,to; }e[N<<1]; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; h[u]=cnt; } bool cmp(const int &a,const int &b) { return f[a]>f[b]; } void dfs(int u,int fa) { f[u]=a[u]; for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fa) dfs(e[i].to,u); tot=0; for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fa) c[++tot]=e[i].to; sort(c+1,c+1+tot,cmp); int p=0; while(p<min(b[u],tot)&&f[c[p+1]]>=0) p++,f[u]+=f[c[p]],g[u]|=g[c[p]]; if((p<tot&&p>0&&f[c[p]]==f[c[p+1]])||(f[c[p]]==0&&p>0)) g[u]=1; } int main() { n=read(); for(int i=2;i<=n;i++) a[i]=read(); b[1]=1e9; for(int i=2;i<=n;i++) b[i]=read()-1; for(int i=1;i<n;i++) { int x=read(),y=read(); add(x,y),add(y,x); } dfs(1,0); printf("%d\n",f[1]); if(!g[1]) puts("solution is unique"); else puts("solution is not unique"); return 0; }