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);
好吧承认看了题解
/*
本题有三种状态,分别是
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 或 最小顶点覆盖=最大匹配(双向图)(HDU 1053)
- [BZOJ1017][JSOI2008][树形DP]魔兽地图DotR
- ZOJ3824 Fiber-optic Network
- hihocoder #1035 : 自驾旅行 III 树形DP
- POJ 3342
- URAL1018
- hdu1561 zoj3201
- poj 3107 Godfather
- zoj3201Tree of Tree
- Codeforces Round #135 (Div. 2)VD. Choosing Capital for Treeland
- POJ 1848 Tree
- HDU 1561 The more, The Better(树形DP)
- UVALive 6436 The Busiest City
- 树形dp简单总结
- Party at Hali-Bula
- zoj cut the tree(树形dp,小细节真的很多)
- poj 2486 Apple Tree(树形dp)
- poj 1155 TELE(树形泛化背包dp)
- 树形DP
- bzoj1040[骑士] 环型森林(树形dp)