1. 程式人生 > >[題解]洛谷P1041 傳染病控制

[題解]洛谷P1041 傳染病控制

max tag i++ namespace eof 說明 define deb ring

這道題的樹沒說明父親和兒子的輸入順序,以前也遇到過,蛋疼

思路:

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; }

[題解]洛谷P1041 傳染病控制