P1272 重建道路(樹形dp)
阿新 • • 發佈:2017-09-03
esp 輸入輸出格式 嚴重 span 地震 std 描述 event i++
P1272 重建道路
題目描述
一場可怕的地震後,人們用N個牲口棚(1≤N≤150,編號1..N)重建了農夫John的牧場。由於人們沒有時間建設多余的道路,所以現在從一個牲口棚到另一個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。John想要知道另一次地震會造成多嚴重的破壞。有些道路一旦被毀壞,就會使一棵含有P(1≤P≤N)個牲口棚的子樹和剩余的牲口棚分離,John想知道這些道路的最小數目。
輸入輸出格式
輸入格式:
第1行:2個整數,N和P
第2..N行:每行2個整數I和J,表示節點I是節點J的父節點。
輸出格式:
單獨一行,包含一旦被破壞將分離出恰含P個節點的子樹的道路的最小數目。
輸入輸出樣例
輸入樣例#1:11 6 1 2 1 3 1 4 1 5 2 6 2 7 2 8 4 9 4 10 4 11輸出樣例#1:
2
說明
【樣例解釋】
如果道路1-4和1-5被破壞,含有節點(1,2,3,6,7,8)的子樹將被分離出來
#include<iostream> #include<cstdio> #include<cstring> #define N 151 using namespace std; int n,m,ans,cnt,flag,w;42分錯誤暴力int head[N],son[N],vis[N]; struct node { int u,v,next; }e[N<<1]; inline int read() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(intu,int v) { e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt; } void dfs2(int u,int tot) { if(son[u]==m) { w=tot; return; } for(int i=head[u];i;i=e[i].next) { int v=e[i].v;if(vis[i])continue; if(son[u]-son[v]>=m) { vis[i]=1; son[u]-=son[v]; tot=tot+1; dfs2(u+1-1,tot); vis[i]=0; } } } void dfs(int u) { if(flag) return; for(int i=head[u];i;i=e[i].next) { dfs(e[i].v); if(son[u]<m) continue; else if(son[u]==m) { printf("1\n"); flag=1;return; } else { int tmp=son[u]; dfs2(u,0); ans=min(ans,w); son[u]=tmp; } } if(flag) return; } void dfs1(int u) { son[u]=1; for(int i=head[u];i;i=e[i].next) { dfs1(e[i].v); son[u]+=son[e[i].v]; } } int main() { int x,y; n=read();m=read(); if(m==1) { printf("1\n"); return 0; } for(int i=1;i<n;i++) { x=read();y=read(); add(x,y); } ans=0x3f3f3f3f;dfs1(1); dfs(1); if(!flag) printf("%d\n",ans); return 0; }
/* 顯然樹形dp dp[i][j]:i為根斷掉子樹大小為j最小邊數 初始化dp[u][1]=1的度數 轉移時枚舉當前點斷掉多少,算出連到的兒子斷掉多少 因為由兒子轉移過來,他們之間的連邊不能斷 但是轉移時斷掉了兩次,所以答案減2 */ #include<iostream> #include<cstdio> #include<cstring> #define N 151 #define inf 0x7f7f7f7f using namespace std; int dp[N][N],head[N],d[N]; int n,m,ans,cnt; struct node { int u,v,next; }e[N<<1]; inline int read() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(int u,int v) { e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt; } void dfs(int u,int fa) { dp[u][1]=d[u]; for(int i=head[u];i;i=e[i].next) { if(e[i].v!=fa) { dfs(e[i].v,u); for(int j=m;j>=1;j--) for(int k=1;k<=j;k++) dp[u][j]=min(dp[u][j],dp[e[i].v][k]+dp[u][j-k]-2); } }ans=min(ans,dp[u][m]); } int main() { int x,y; memset(dp,1,sizeof dp); n=read();m=read(); for(int i=1;i<n;i++) { x=read();y=read(); add(x,y);add(y,x); d[x]++;d[y]++; } ans=inf; dfs(1,0); printf("%d\n",ans); return 0; }
P1272 重建道路(樹形dp)