P1041 传染病控制(noip2003)(搜索)
Posted ajmddzp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1041 传染病控制(noip2003)(搜索)相关的知识,希望对你有一定的参考价值。
呃呃呃。。。真的是惨烈啊。。。
今天的模拟赛是真的惨。。。。。
本题,正解居然是搜索!!!!!!
蒟蒻自己歪歪了一个貌似是正解但是却连一半都没过的错解。
先解释一下自己的dp思路把。
$f[i][u][v][0/1]$表示第i秒(等效于深度)uv之间的边断还是不断。
转移有两个:
$f[dep[u]][u][v][1]=size[v];$表示此边断,然后下面的点全对答案有贡献
然后找到v的儿子
$f[dep[u]][u][v][0]=max(f[dep[u]][u][v][0],max(f[dep[v]][u][j][0],f[dep[v]][u][j][1]));$
临收卷前发现貌似第二维可以压掉,也就是:$f[dep[v]][v][0/1]$表示v上面那个边要不要删。
然后发现随手hack....
于是,我发现答案统计的时候,会有惊人的重复计算。
于是,我歪歪了好久,怎么标记统计过了,怎么返回,怎么....
然后....发现最后好像被我打成了贪心???
我在每一层去最大值,然后标记,返回,从别的子树里找最大值,然后一直重复到底层。
于是...我抱着能A掉这题的心情,笑了起来。。。
然后我rand了好多的的数据,都没有hack掉,我更开心了。
(先放dp代码:)
#include<bits/stdc++.h> #define g(x) for(int i=head[x];i;i=e[i].next) #define l(x) for(int l=head[x];l;i=e[l].next) using namespace std; const int maxn=505; int n,p; struct edge { int to,next; }e[maxn]; int head[maxn],cnt; void addedge(int from,int to) { e[++cnt]=(edge){to,head[from]}; head[from]=cnt; } int dep[maxn]; int size[maxn]; int fa[maxn]; void dfs(int u,int f) { dep[u]=dep[f]+1; size[u]=1; fa[u]=f; g(u) { int v=e[i].to; if(v==f) continue; dfs(v,u); size[u]+=size[v]; } } int f[maxn][maxn][2]; int mp; void dp(int u) { g(u) { int v=e[i].to; if(v==fa[u]) continue; dp(v); f[dep[u]][u][v][1]=size[v]; for(int j=1;j<=n;j++) if(fa[j]==v) f[dep[u]][v][0]=max(f[dep[u]][v][0],max(f[dep[v]][j][0],f[dep[v]][j][1])); } } int ans; int vis[maxn]; void getans(int u) { int m=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa[u]) continue; m=max(m,max(f[dep[u]][v][1],f[dep[u]][v][0])); } for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa[u]) continue; if(m==f[dep[u]][v][1]&&vis[u]==0) { ans+=m; vis[u]=1; continue; } else { getans(v); } } } int main() { scanf("%d%d",&n,&p); for(int i=1;i<=p;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } addedge(0,1); dfs(1,0); dp(1); for(int i=1;i<=n;i++) mp=max(mp,dep[i]); getans(1); printf("%d",n-ans); return 0; }
以上是关于P1041 传染病控制(noip2003)(搜索)的主要内容,如果未能解决你的问题,请参考以下文章