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;
    }
}
View Code

 

posted @ 2014-03-10 19:50  等待最好的两个人  阅读(176)  评论(0编辑  收藏  举报