[题解]洛谷P1041 传染病控制
这道题的树没说明父亲和儿子的输入顺序,以前也遇到过,蛋疼
思路:
1)ans=总点数-隔离了的点数
2)第i次隔离的边一定是深度为i的点和深度为i-1的点的连边,所以用vector存每层的点
3)预处理f[i]储存以i为根的子树的点数
4)已经被隔离了的点就不用了搜惹
5)由于隔离了的点数是单调递增的,所以不用判断深度是否达到最大深度,直接在每一层结束时更新最大值(否则因为上面的剪枝,最后一层的点早已被隔离时,就统计不到惹)
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<vector> using namespace std; const int MAXN = 310,MAXP = 310; #define DEBUG(x) cout<< #x <<":"<< x <<endl inline int read(){ int x=0,w=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')w=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } return x*w; } int n,p; int first[MAXN]; vector<int>node[MAXP]; struct edge{ int u,v,next; }e[MAXP*2]; int tot=0; void insert(int u,int v){ e[++tot].u=u;e[tot].v=v;e[tot].next=first[u];first[u]=tot; } int fa[MAXN],d[MAXN],f[MAXN],vis[MAXN]={0},deep=0; void init(int x,int fat){ f[x]=1; if(x!=1){ d[x]=d[fat]+1; fa[x]=fat; } deep=max(d[x],deep); node[d[x]].push_back(x); for(int i=first[x];i!=-1;i=e[i].next){ if(e[i].v!=fat){ init(e[i].v,x); f[x]+=f[e[i].v]; } } } void tag(int x,int num){ vis[x]=num; for(int i=first[x];i!=-1;i=e[i].next){ int v=e[i].v; if(v!=fa[x]){ tag(v,num); } } } int ans=0; void solve(int x,int o){ for(int i=0;i<node[x].size();i++){ int u=node[x][i]; if(vis[u])continue; tag(u,1); solve(x+1,o+f[u]); tag(u,0); } ans=max(ans,o); } int main(){ memset(first,-1,sizeof(first)); n=read();p=read(); for(int i=1;i<=p;i++){ int u=read(),v=read(); insert(u,v);insert(v,u); } d[1]=0; init(1,-1); solve(1,0); printf("%d\n",n-ans); return 0; }
本篇文章为SHINE_GEEK原创,转载请注明来源!
-------------------------------------
签名:自己选的路,跪着也要走完;理想的实现,需要不懈奋斗!
-------------------------------------
written_by:SHINE_GEEK
blog_addr:www.cnblogs.com/sjrb
-------------------------------------
签名:自己选的路,跪着也要走完;理想的实现,需要不懈奋斗!
-------------------------------------