您的位置:首页 > 其它

pku1848 Tree 树形DP

2016-03-20 18:34 330 查看
这题最坑的地方在于,我以为对于输入的边一定是y的父亲是x,英语实力捉急的我= =

好吧承认看了题解

/*
本题有三种状态,分别是
dp[u][0],以u为根,所有的点都在环内
dp[u][1],以u为根,除了u外其余的都在环内
dp[u][2],以u为根,除了u和与u点相连的链(至少有两个点)外,其余的点都在环内
有四种状态转移
1、所有子节点都满足在环内,只有根节点不在环内,
dp[u][1]=min(INF,sum);(sum是所有的dp[v][0]的和)
2、有一个子节点不在环内,以该子节点有一条链,将此链连到以u为根的树上,(+1)就可以使得u的所有子节点都在环内
dp[u][0]=min(dp[u][0],sum-dp[v][0]+dp[v][2]+1);
3、有一个子节点不在环内,其余自己处理,
dp[u][2]=min(dp[u][2],sum-dp[v][0]+min(dp[v][1],dp[v][2]));
4、有两个不在环内,将这两个加一条边连起来就可使得所有都在环内
dp[u][0]=min(dp[u][0],sum-dp[v][0]-dp[k][0]+min(dp[v][1],dp[v][2])+min(dp[k][1],dp[k][2])+1);
Problem: 1848		User: BPM136
Memory: 720K		Time: 0MS
Language: G++		Result: Accepted

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#include<vector>
#define LL long long
#define pb push_back
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define dfo(i,a,b) for(int i=a;i>=b;i--)
#define efo(i,x) for(int i=last[x];i!=0;i=e[i].next)
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
#define N 105
#define inf 10000
struct edge
{
int y,next;
}e[N*4];
int last[N*3],ne=0;
int du[N*3];
int f[N*3][3];
int n;
bitset<N>v;

void add(int x,int y)
{
e[++ne].y=y;e[ne].next=last[x];last[x]=ne;
}

void dfs(int x)
{
int sum=0;
v[x]=1;
vector<int>ch;
efo(i,x)
if(v[e[i].y]==0)
{
dfs(e[i].y);
sum+=f[e[i].y][0];
ch.pb(e[i].y);
}
f[x][0]=f[x][2]=inf;
f[x][1]=0;
if(du[x]==1&&x!=1)return ;
f[x][1]=min(inf,sum);
fo(i,0,ch.size()-1)
{
f[x][0]=min(f[x][0],f[ch[i]][2]+sum-f[ch[i]][0]+1);
f[x][2]=min(f[x][2],min(f[ch[i]][1],f[ch[i]][2])+sum-f[ch[i]][0]);
fo(j,0,ch.size()-1)
if(i!=j)
{
int t1=min(f[ch[i]][1],f[ch[i]][2]);
int t2=min(f[ch[j]][1],f[ch[j]][2]);
int ret=t1+t2+1+sum-f[ch[i]][0]-f[ch[j]][0];
f[x][0]=min(f[x][0],ret);
}
}
//	cout<<x<<' '<<f[x][0]<<' '<<f[x][1]<<' '<<f[x][2]<<endl;
}

int main()
{
memset(du,0,sizeof(du));
n=read();
fo(i,1,n-1)
{
int x=read(),y=read();
add(x,y);add(y,x);
du[x]++;du[y]++;
//		fa[y]=x;
}
v.reset();
//	fo(i,1,n)cout<<fa[i]<<' ';cout<<endl;
dfs(1);
if(f[1][0]>=inf)puts("-1");
else cout<<f[1][0]<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树形DP