1. 程式人生 > >poj1463 樹形dp

poj1463 樹形dp

event cout next ber none 數字 [1] span ==

樹形dp裸題,不過輸入是真的惡心,要字符串讀入考慮數字大於等於10的情況

dp[i][j]表示i的子樹在j狀態的最小的邊集覆蓋,j為0表示不選當前結點,1表示選

轉移方程(u->x是u的所有子節點)dp[u][0]+=dp[x][1],dp[u][1]+=min(dp[x][0],dp[x][1]),dp[u][1]+=1(要選自己)

技術分享
#include<cstdio>
#include<iostream>
#include<cstring>
#define fi first
#define se second
#define mp make_pair
#define
pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; using namespace __gnu_cxx; const double g=10.0,eps=1e-7; const int N=1500+10,maxn=60000+10,inf=0x3f3f3f3f
; struct edge{ int to,Next; }e[N<<2]; int dp[N][2]; int head[N],cnt; void add(int u,int v) { e[cnt].to=v; e[cnt].Next=head[u]; head[u]=cnt++; } void dfs(int u,int f) { dp[u][1]=1; for(int i=head[u];~i;i=e[i].Next) { int x=e[i].to;
if(x==f)continue; dfs(x,u); dp[u][0]+=dp[x][1]; dp[u][1]+=min(dp[x][0],dp[x][1]); } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; while(cin>>n) { memset(head,-1,sizeof head); cnt=0; for(int i=0; i<n; i++) { string s; cin>>s; int a=0,id=0; while(id+1<s.size()&&s[id+1]!=:)id++; // cout<<id<<endl; for(int i=0;i<=id;i++)a=a*10+(int)(s[i]-0); // cout<<a<<endl; int k=0,id1=id+3; while(id1+1<s.size()&&s[id1+1]!=))id1++; for(int i=id+3;i<=id1;i++)k=k*10+(int)(s[i]-0); // cout<<k<<endl; while(k--) { int b; cin>>b; add(a,b); add(b,a); } } memset(dp,0,sizeof dp); dfs(1,-1); cout<<min(dp[1][0],dp[1][1])<<endl; } return 0; } /************ 11 0:(10) 1 2 3 4 5 6 7 8 9 10 1:(0) 2:(0) 3:(0) 4:(0) 5:(0) 6:(0) 7:(0) 8:(0) 9:(0) 10:(0) ************/
View Code

poj1463 樹形dp