您的位置:首页 > 其它

BZOJ 1907: 树的路径覆盖 树型dp

2017-08-19 11:17 309 查看

1907: 树的路径覆盖

Time Limit: 5 Sec  Memory Limit: 259 MB
Submit: 755  Solved: 351

[Submit][Status][Discuss]

Description



Input



Output



Sample Input

1

7

1 2

2 3

2 4

4 6

5 6

6 7

Sample Output

3

HINT


,注意此注释有误,第二种情况应该为{1,2,4,5,6},{3},{7}

转载

其实挺sb的一个树形dp。。我这种sb都会的树形dp。。 
。。我的做法很鬼畜。 
fx,0,fx,1分别表示点x作为转折点(也就是连成一个V字形)/非转折点,覆盖该子树的最小路径数。 
记v为x的儿子节点,sum=∑min(fv,0,fv,1). 
Mn,mn为fv,0−min(fv,0,fv,1)的最小值和次小值 
fx,0=min(sum+Mn) 
fx,1=min(sum+Mn+mn−1)

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=10100,inf=0X3f3f3f3f;

int n,ecnt,last
;
struct EDGE{int to,nt;}e[N<<1];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}

int f
[2];

void dfs(int u,int fa)
{
register int i,sum=0,mn=inf,MN=inf,now=inf;
for(i=last[u];i;i=e[i].nt)
{
if(e[i].to==fa)continue;
dfs(e[i].to,u);
sum+=min(f[e[i].to][0],f[e[i].to][1]);
now=f[e[i].to][0]-min(f[e[i].to][1],f[e[i].to][0]);
if(now<MN)mn=MN,MN=now;else if(now<mn)mn=now;
}
f[u][0]=f[u][1]=sum+1;
if(MN!=inf)f[u][0]=min(f[u][0],sum+MN);
if(mn!=inf)f[u][1]=min(f[u][1],sum+mn+MN-1);
f[u][1]=min(f[u][1],f[u][0]);
}

int main()
{
int T=read();
register int i,u,v;
while(T--)
{
n=read();
ecnt=0;
memset(last+1,0,sizeof(int)*n);
for(i=1;i<n;++i)
{
u=read();v=read();
add(u,v);add(v,u);
}
dfs(1,0);
print(min(f[1][0],f[1][1]));puts("");
}
return 0;
}
/*
1
7
1 2
2 3
2 4
4 6
5 6
6 7

3
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: