Description
Input
Output
Sample Input
5
1 3
5 2
4 3
3 5
Sample Output
2
Hint
【数据规模】
1 ≤ N ≤ 10000
这道题不是最水的树形DP吗?
只不过题意比较难懂一点。
翻译出来,草地就是一棵树。
然后就成为了树的最小支配集问题。
可以贪心,
可以DP。
附上我的DP代码:
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
struct node{
int to;
int next;
}w[20005];
int cnt=1;
int h[10005];
int F[3][10005];
void AddEdge(int x,int y){
cnt++;
w[cnt].to=y;
w[cnt].next=h[x];
h[x]=cnt;
}
int Tree_DP(int v,int fa,int flag){
if(F[flag][v])return F[flag][v];
if(flag==0){
F[flag][v]=1;
for(int i=h[v];i;i=w[i].next){
int y=w[i].to;
if(y!=fa){
F[flag][v]+=min(Tree_DP(y,v,0),min(Tree_DP(y,v,1),Tree_DP(y,v,2)));
}
}
}
if(flag==1){
int temp=Tree_DP(v,fa,2);
F[flag][v]=0x7fffffff;
for(int i=h[v];i;i=w[i].next){
int y=w[i].to;
if(y!=fa){
F[flag][v]=min(F[flag][v],temp-min(Tree_DP(y,v,0),Tree_DP(y,v,1))+Tree_DP(y,v,0));
}
}
}
if(flag==2){
for(int i=h[v];i;i=w[i].next){
int y=w[i].to;
if(y!=fa){
F[flag][v]+=min(Tree_DP(y,v,0),Tree_DP(y,v,1));
}
}
}
return F[flag][v];
}
int main(){
int n;
scanf("%d",&n);
int x,y;
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
printf("%d",min(Tree_DP(1,0,0),Tree_DP(1,0,1)));
return 0;
}
下面是DYF神犇的贪心代码:
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
int cnt,to[20005],nxt[20005],h[20005],n;
void cs(int a,int b){
cnt++;to[cnt]=b;nxt[cnt]=h[a];h[a]=cnt;
}
int f[10005];int ans;
void dfs(int x,int fa){
int flg=0;
for (int i=h[x];i;i=nxt[i]){
if (to[i]==fa)continue;
dfs(to[i],x);
if (f[to[i]])flg=1;
}
if (flg==0&&!f[x]&&!f[fa])f[fa]=1,ans++;
}
int main(){
cin>>n;
for (int i=1;i<n;i++){
int a,b;
cin>>a>>b;
cs(a,b);cs(b,a);
}
dfs(1,0);
cout<<ans;
return 0;
}