1907: 树的路径覆盖
Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 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
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[N];
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[N][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
*/