boj1267 Infinite’s Cave 树形dp + 背包
题目链接:http://acm.bupt.edu.cn/onlinejudge/newoj/showProblem/show_problem.php?problem_id=1267
/**算法分析: */ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<string> #include<map> #include<set> #include<cmath> #include<sstream> #include<queue> #include<utility> #define MAXN 505 #define PI acos(-1.0) #define INF 0x3f3f3f3f #define REP(i,n) for(int i=0; i<n; i++) #define FOR(i,s,t) for(int i=s; i<=t; i++) #define show(x) { cerr<<">>>"<<#x<<" = "<<x<<endl; } #define showtwo(x,y) { cerr<<">>>"<<#x<<"="<<x<<" "<<#y<<" = "<<y<<endl; } using namespace std; int n,q; int dp1[MAXN][MAXN]; //dp1[i][j]代表以i为根访问j个点并回到第i个点的最小路程代价 int dp2[MAXN][MAXN]; //dp2[i][j]代表以i为根访问j个点不回到第i个点的最小路程代价 int num[MAXN]; vector<pair<int,int> > G[MAXN]; struct Store { int x,id; bool operator < (const Store& rhs) const { return x < rhs.x; } }a[MAXN*2]; int ans[MAXN*2]; void dfs_count(int u) { num[u] = 1; int sz = G[u].size(); REP(i,sz) { int v = G[u][i].first; dfs_count(v); num[u] += num[v]; } } void dfs(int u,int cnt) //连根一起共访问cnt个点 { if(dp2[u][cnt] != INF) return; int sz = G[u].size(); REP(i,sz) { int v = G[u][i].first; int d = G[u][i].second; dfs(v,num[v]); for(int k=cnt; k>=2; k--) //枚举以u为根的树访问点的个数 for(int j=1; j<=min(num[v],k-1); j++) //v这个子树要走j个点 { dp1[u][k] = min(dp1[u][k],2*d+dp1[v][j]+dp1[u][k-j]); dp2[u][k] = min(dp2[u][k],2*d+dp1[v][j]+dp2[u][k-j]); dp2[u][k] = min(dp2[u][k],d+dp2[v][j]+dp1[u][k-j]); } } } int main() { //freopen("E:\\acm\\input.txt","r",stdin); int test_count = 1; while(cin>>n && n) { printf("Case %d:\n",test_count++); bool not_root[MAXN]; memset(not_root,0,sizeof(not_root)); memset(dp1,0x3f,sizeof(dp1)); memset(dp2,0x3f,sizeof(dp2)); REP(i,n) G[i].clear(); REP(i,n-1) { int v,u,d; scanf("%d%d%d",&v,&u,&d); not_root[v] = true; G[u].push_back(make_pair(v,d)); } int root; REP(i,n) if(!not_root[i]) root = i; REP(i,n) dp1[i][1] = dp2[i][1] = dp1[i][0] = dp2[i][0] = 0; dfs_count(root); dfs(root,n); //FOR(i,1,n) showtwo(dp2[root][i],num[i-1]); cin>>q; REP(i,q) { scanf("%d",&a[i].x); a[i].id = i; } sort(a,a+q); int ptr = 1; REP(i,q) { while(ptr<=n && dp2[root][ptr] <= a[i].x) ptr++; ans[a[i].id] = ptr-1; } REP(i,q) cout<<ans[i]<<endl; } }