[树形DP]JZOJ 3347 树的难题
分析
显然最优解只有三种:
树中有若干白色点,无黑点
有若干黑点,无白点
有若干黑点,一白点
设成DP,转移较简单
注意DP不能用DFS转移,会爆栈
其实我不明白为什么他不出个菊花图来卡我的DP,DP复杂度约为O(n*最大儿子数)
#pragma GCC optimize(2) #include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> #include <queue> using namespace std; typedef long long ll; const int N=3e5+10; const ll Inf=3e15; struct Graph { int v,nx; ll w; }g[2*N]; ll f[N][3]; int cnt,list[N],fa[N],dep[N]; int w[N],a[N]; int t,n; void Add(int u,int v,int w) { g[++cnt]=(Graph){v,list[u],w};list[u]=cnt; g[++cnt]=(Graph){u,list[v],w};list[v]=cnt; } void BFS(int v0) { queue<int> q; while (!q.empty()) q.pop(); q.push(v0);dep[v0]=1; while (!q.empty()) { int u=q.front();q.pop(); for (int i=list[u];i;i=g[i].nx) if (!dep[g[i].v]) { dep[g[i].v]=dep[u]+1;fa[g[i].v]=u; q.push(g[i].v); } } } bool CMP(int a,int b) { return dep[a]>dep[b]; } int main() { for (scanf("%d",&t);t;t--) { cnt=0;memset(list,0,sizeof list); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&w[i]),a[i]=i; for (int i=1,u,v,w;i<n;i++) scanf("%d%d%d",&u,&v,&w),Add(u,v,w); memset(f,0,sizeof f);memset(dep,0,sizeof dep); BFS(1); sort(a+1,a+n+1,CMP); for (int i=1;i<=n;i++) { int u=a[i]; if (w[u]==0) { f[u][0]=Inf;f[u][2]=Inf; for (int j=list[u];j;j=g[j].nx) if (g[j].v!=fa[u]) { f[u][1]+=min(min(f[g[j].v][0],f[g[j].v][2])+g[j].w,f[g[j].v][1]); ll t=0; for (int k=list[u];k;k=g[k].nx) if (k!=j&&g[k].v!=fa[u]) t+=min(min(f[g[k].v][0],f[g[k].v][2])+g[k].w,f[g[k].v][1]); f[u][2]=min(f[u][2],f[g[j].v][2]+t); } } if (w[u]==1) { f[u][1]=Inf; for (int j=list[u];j;j=g[j].nx) if (g[j].v!=fa[u]) { f[u][0]+=min(f[g[j].v][0],min(f[g[j].v][1],f[g[j].v][2])+g[j].w); f[u][2]+=min(f[g[j].v][1],min(f[g[j].v][0],f[g[j].v][2])+g[j].w); } } if (w[u]==2) { f[u][2]=Inf; for (int j=list[u];j;j=g[j].nx) if (g[j].v!=fa[u]) { f[u][0]+=min(f[g[j].v][0],min(f[g[j].v][1],f[g[j].v][2])+g[j].w); f[u][1]+=min(f[g[j].v][1],min(f[g[j].v][0],f[g[j].v][2])+g[j].w); ll t=0; for (int k=list[u];k;k=g[k].nx) if (k!=j&&g[k].v!=fa[u]) t+=min(f[g[k].v][1],min(f[g[k].v][0],f[g[k].v][2])+g[k].w); f[u][2]=min(f[u][2],f[g[j].v][2]+t); } } } printf("%lld\n",min(f[1][0],min(f[1][1],f[1][2]))); } }
在日渐沉没的世界里,我发现了你。