POJ 3345

题意:一个国家想贿赂至少m个国家,给出贿赂每个国家需要的钱及他们的附属关系。如果贿赂了主国,其从属国家也同样视为被贿赂了,且关系网无环。

题解:树形DP,dp[now][i]为以第now国家为子树的国家团体贿赂了i个国家所需要的最小花费,在建立一个虚拟结点0,让它与所有主国建立一条边。

View Code
  1 #include<cstdio>

  2 #include<cstring>

  3 #include<algorithm>

  4 #include<map>

  5 #include<string>

  6 using namespace std;

  7 map<string,int> MP;

  8 const int inf=0x3f3f3f3f;

  9 int dp[300][300],tot[300],val[300],head[300],nc,n,m;

 10 bool vis[300];

 11 struct Edge

 12 {

 13     int to,next;

 14 }edge[300*300];

 15 void add(int a,int b)

 16 {

 17     edge[nc].to=b;edge[nc].next=head[a];head[a]=nc++;

 18 }

 19 void dfs(int now)

 20 {

 21     vis[now]=true;

 22     dp[now][0]=0;

 23     tot[now]=0;

 24     for(int i=head[now];i!=-1;i=edge[i].next)

 25     {

 26         int to=edge[i].to;

 27         if(!vis[to])

 28             dfs(to);

 29         int num=tot[to],all=tot[now]+tot[to];

 30         tot[now]=all;

 31         for(int i=all;i>=1;i--)

 32         {

 33             for(int j=0;j<=num&&j<=i;j++)

 34             {

 35                 dp[now][i]=min(dp[now][i],dp[now][i-j]+dp[to][j]);

 36             }

 37         }

 38     }

 39     dp[now][++tot[now]]=val[now];

 40 }

 41 int main()

 42 {

 43     char s[100000];

 44     while(gets(s),strcmp(s,"#")!=0)

 45     {

 46         sscanf(s,"%d%d",&n,&m);

 47         memset(head,-1,sizeof(head));

 48         memset(vis,false,sizeof(vis));

 49         memset(val,0,sizeof(val));

 50         memset(dp,0x3f,sizeof(dp));

 51         nc=0;MP.clear();

 52         int num=0;

 53         for(int i=1,j,k,id;i<=n;i++)

 54         {

 55             gets(s);

 56             char tp[100];

 57             for(j=0;s[j]!=' ';j++);

 58             s[j]='\0';

 59             strcpy(tp,s);

 60             for(++j,k=0;s[j]!='\0'&&s[j]!=' ';j++)

 61                 k=k*10+s[j]-'0';

 62             if(MP.find(tp)==MP.end())

 63                 id=MP[tp]=++num;

 64             else

 65                 id=MP[tp];

 66             val[id]=k;

 67             if(s[j]=='\0')

 68                 continue;

 69             else

 70             {

 71                 for(k=++j;s[j]!='\0';j++)

 72                 {

 73                     if(s[j]==' ')

 74                     {

 75                         s[j]='\0';

 76                         strcpy(tp,s+k);

 77                         if(MP.find(tp)!=MP.end())

 78                             add(id,MP[tp]);

 79                         else

 80                             add(id,MP[tp]=++num);

 81                         vis[MP[tp]]=true;

 82                         k=j+1;

 83                     }

 84                 }

 85                 if(s[k]!=' '&&s[k]!='\0')

 86                 {

 87                     strcpy(tp,s+k);

 88                     if(MP.find(tp)!=MP.end())

 89                         add(id,MP[tp]);

 90                     else

 91                         add(id,MP[tp]=++num);

 92                     vis[MP[tp]]=true;

 93                 }

 94             }

 95         }

 96         val[0]=inf;

 97         for(int i=1;i<=num;i++)

 98             if(!vis[i])

 99                 add(0,i);

100         memset(vis,false,sizeof(vis));

101         dfs(0);

102         int ans=inf,len=tot[0];

103         for(int i=m;i<len;i++)

104             ans=min(ans,dp[0][i]);

105         printf("%d\n",ans);

106     }

107     return 0;

108 }

你可能感兴趣的:(poj)