bzoj 1907: 樹的路徑覆蓋【貪心+樹形dp】
阿新 • • 發佈:2018-01-04
string cpp print names pos else ++ () post
我是在在做網絡流最小路徑覆蓋的時候找到這道題的
然後發現是個貪心+樹形dp
\( f[i] \)表示在\( i \)為根的子樹中最少有幾條鏈,\( v[i] \) 表示在\( i \)為根的子樹中\( i \) 是( 0)否(1)為一條鏈的端點
然後貪心轉移即可(有鏈端點則連起來)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=10005;
int T,n,h[N],cnt,f[N];
bool v[N];
struct qwe
{
int ne,to,va;
}e[N<<1];
void add(int u,int v)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
}
void dfs(int u,int fa)
{
int con=0;
f[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fa)
{
dfs(e[i].to,u);
f[u]+=f[e[i].to];
if (!v[e[i].to])
con++;
}
if(con==1)
f[u]--;//減掉本身
else if(con>1)
f[u]-=2,v[u]=1;//減掉本身和其中一個端點
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(h,0,sizeof(h));
memset(e,0,sizeof(e));
memset(f,0,sizeof(f));
memset(v,0 ,sizeof(v));
cnt=0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0);
printf("%d\n",f[1]);
}
return 0;
}
bzoj 1907: 樹的路徑覆蓋【貪心+樹形dp】