建立一个虚点(权为无穷大),从它到每个入度为 0 的点都连一条边,然后做树型DP。
先递归算出子结点的 f 值,然后用背包的方法计算父结点的 f 值。

/*************************************************************************
Author: WHU_GCC
Created Time: 2007-8-14 12:22:37
File Name: pku3345.cpp
Description: 
***********************************************************************
*/

#include 
<iostream>
#include 
<sstream>
#include 
<vector>
using namespace std;
#define out(x) (cout<<#x<<": "<<x<<endl)
const int maxint=0x7FFFFFFF;
typedef 
long long int64;
const int maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template
<class T>void show(T a, int n){for(int i=0; i<n; ++i) cout<<a[i]<<' '; cout<<endl;}
template
<class T>void show(T a, int r, int l){for(int i=0; i<r; ++i)show(a[i],l);cout<<endl;}

int n, m;

vector 
<int> child[300];
vector 
<string> child_name[300];
string name[300];
int dia[300];
int after[300];

int f[300][300];
int used[300];
int p[300];
int q[300];

int dfs(int x)
{
    
int ret = 0;
    
if (used[x]) return after[x];
    
for (int i = 0; i < child[x].size(); i++)
        ret 
+= dfs(child[x][i]);
    
    
for (int i = 0; i <= n; i++) p[i] = maxint;
    p[
0= 0;
    
for (int i = 0; i < child[x].size(); i++)
    
{
        
for (int j = 0; j <= n; j++) q[j] = maxint;
        
for (int k = n; k >= 0; k--if (p[k] != maxint)
        
{
            
for (int j = 0; k + j <= n; j++if (f[child[x][i]][j] != maxint)
                q[k 
+ j] <?= p[k] + f[child[x][i]][j];
        }

        
for (int j = 0; j <= n; j++) p[j] <?= q[j];
    }

    used[x] 
= 1;
    after[x] 
= ret + 1;
    p[after[x]] 
<?= dia[x];
    memcpy(f[x], p, 
sizeof(p));
    
    
return after[x];
}


int in_deg[300];

int main()
{
    
char s[1000];
    
while (gets(s), strcmp(s, "#"!= 0)
    
{
        
if (strcmp(s, ""== 0continue;
        stringstream ss(s);
        ss 
>> n >> m;
        
for (int i = 0; i < n; i++)
        
{
            child_name[i].clear();
            child[i].clear();
            
char s[100000];
            scanf(
"%s%d", s, &dia[i]);
            name[i] 
= s;
            gets(s);
            stringstream ss(s);
            
string t;
            
while (ss >> t)
                child_name[i].push_back(t);
        }

        memset(in_deg, 
0sizeof(in_deg));
        
for (int i = 0; i < n; i++)
            
for (int j = 0; j < child_name[i].size(); j++)
            
{
                
for (int k = 0; k < n; k++if (child_name[i][j] == name[k])
                
{
                    child[i].push_back(k);
                    in_deg[k]
++;
                    
break;
                }

            }

        child[n].clear();
        
for (int i = 0; i < n; i++if (in_deg[i] == 0)
            child[n].push_back(i);
        dia[n] 
= maxint;
            
        memset(used, 
0sizeof(used));
        memset(after, 
0sizeof(after));
        memset(f, 
0sizeof(f));
        dfs(n);
        
int ans = maxint;
        
for (int i = m; i <= n; i++) ans <?= f[n][i];
        printf(
"%d\n", ans);
    }

    
return 0;
}
posted on 2007-08-15 18:42 Felicia 阅读(618) 评论(0)  编辑 收藏 引用 所属分类: 动态规划

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理