P1453 城市环路
一道环套树,套树dp(十分水)。
对于环上每一个点,都在子树中dp求出取这个点和不取的值,最后在这个环上强制一条边上的两个点不能同时选,dp两次,取最大值即可。
虽然貌似知道强制删掉一条边dp一边就可以……但是复杂度是一样的,怎么写开心怎么来!
一开始0分,因为需要用的数组下标是1,2,然而我就开了2……开3就90……
最后发现没有暴力删边,加上就AC了……
代码:
#include<cstdio> #include<queue> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 200005 typedef double db; struct node { int id,no[3]; db val; } q[maxn]; int head[maxn],to[maxn],nxt[maxn],fa[maxn]; db f[maxn][2],us[maxn][2],w[maxn],ans; bool inc[maxn],vis[maxn],flag; int n,cnt,tot; db K; void add(int a,int b) { to[++cnt]=b; nxt[cnt]=head[a]; head[a]=cnt; } void dfs(int u,int faa) { if(flag) return ; vis[u]=1; fa[u]=faa; for(int i=head[u]; i; i=nxt[i]) { int v=to[i]; if(v==faa) continue; if(vis[v]) { if(inc[v]) continue; int x=u; int tmp; while(x!=v) { q[++tot].id=x; q[tot].val=w[x]; inc[x]=1; x=fa[x]; } q[++tot].id=v; q[tot].val=w[v]; inc[v]=1; flag=1; } dfs(v,u); } } void dp(int u,int faa,int o) { f[u][1]=w[u]; for(int i=head[u]; i; i=nxt[i]) { int v=to[i]; if(v==faa) continue; if(o) if(v==q[o].no[1]||v==q[o].no[2]) continue; dp(v,u,0); f[u][1]+=f[v][0]; f[u][0]+=max(f[v][0],f[v][1]); ans=max(f[u][1],f[u][0]); } } int main() { scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%lf",&w[i]); for(int i=1; i<=n; i++) { int a,b; scanf("%d%d",&a,&b); ++a; ++b; add(a,b); add(b,a); } scanf("%lf",&K); dfs(1,0); for(int i=2;i<tot;i++) { q[i].no[1]=q[i-1].id; q[i].no[2]=q[i+1].id; } q[1].no[1]=q[tot].id; q[1].no[2]=q[2].id; q[tot].no[1]=q[tot-1].id; q[tot].no[2]=q[1].id; for(int i=1; i<=tot; i++) dp(q[i].id,0,i); us[1][1]=f[q[1].id][1]; us[1][0]=f[q[1].id][0]; for(int i=2; i<=tot; i++) { int u=q[i].id; us[i][1]=f[u][1]; us[i][0]=f[u][0]; us[i][1]+=us[i-1][0]; us[i][0]+=max(us[i-1][1],us[i-1][0]); } ans=max(ans,us[tot][0]); for(int i=1;i<=tot;i++) us[i][0]=us[i][1]=0; us[1][1]=-999999999.0; us[1][0]=f[q[1].id][0]; for(int i=2; i<=tot; i++) { int u=q[i].id; us[i][1]=f[u][1]; us[i][0]=f[u][0]; us[i][1]+=us[i-1][0]; us[i][0]+=max(us[i-1][1],us[i-1][0]); } ans=max(ans,max(us[tot][1],us[tot][0])); printf("%.1lf\n",ans*K); return 0; }