您的位置:首页 > 其它

P1272 重建道路(树形dp)

2017-09-03 17:34 281 查看

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;
int head
,son
,vis
;
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 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;
}


42分错误暴力

/*
显然树形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

,head
,d
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: