POJ 3345 Bribing FIPA 树形背包+字符串处理

来源:互联网 发布:微谱数据库怎么进去 编辑:程序博客网 时间:2024/06/08 00:17

题意:在树形结构中,每删除一个节点包含一定费用。其中,若一棵子树的祖先节点被删,那么,它的子孙也同时被删除,且不需要支付额外费用。问删去m或者更多的节点的最下费用。

做法:树形背包。树形结构会有多个,形成一片森林。所以最好还要进行一次01背包,应该算简单。

#include<stdio.h>#include<string.h>#define eps 1e8#define LMT 205typedef struct{    int u,v,next;}line;line e[LMT];int wei[LMT],next[LMT],dp[LMT][LMT],son[LMT],fa[LMT],cost[LMT];char nam[LMT][105];int all,ana,n,m;inline int min(int a,int b){    return a<b?a:b;}int search(char *s){    int i;    for( i=0;i<ana;i++)    if(strcmp(s,nam[i])==0)return i;    strcpy(nam[i],s);ana++;    return i;}void insert(int u,int v){    e[all].u=u;    e[all].v=v;    e[all].next=next[u];    next[u]=all++;}int get(void){    char cc=getchar();    int s=0;    while(cc<'0'||cc>'9')    {        if(cc=='#')return 0;        cc=getchar();    }    while(cc>='0'&&cc<='9')    {        s*=10;        s+=cc-'0';        cc=getchar();    }    return s;}int get2(char *s){    char cc=getchar();    int i=0;    while(!(cc>='a'&&cc<='z'||cc>='A'&&cc<='Z'))    {        if(cc=='\n')return 1;        cc=getchar();    }    while(cc>='a'&&cc<='z'||cc>='A'&&cc<='Z')    {        s[i++]=cc;        cc=getchar();    }            s[i]=0;    if(cc=='\n')return 0;    return 1;}void inidfs(int u,int pre){    son[u]=1;    int v,x;    for(x=next[u];x!=-1;x=e[x].next)    if(e[x].v!=pre)    {        v=e[x].v;        if(son[v]==-1)inidfs(v,u);        son[u]+=son[v];    }}void dfs(int u,int pre){    dp[u][son[u]]=wei[u];    int v,x,j,k;    for(x=next[u];x!=-1;x=e[x].next)    if(e[x].v!=pre)    {        v=e[x].v;        dfs(v,u);        for(j=son[u];j>=0;j--)          for(k=0;k<=son[v]&&k<=j;k++)          if(dp[u][j-k]!=eps)          dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]);    }}int main(){    int i,j,k,ans;    char cn[105];    while(1)    {        n=get();        if(0==n)break;        scanf("%d",&m);        memset(next,-1,sizeof(next));        memset(son,-1,sizeof(son));        memset(fa,-1,sizeof(fa));        for(i=0;i<n;i++)        {            for(j=1;j<=n;j++)            dp[i][j]=eps;           dp[i][0]=0;        }        all=0;ana=0;        for(i=1;i<=n;i++)        {            int u,v;            scanf("%s",cn);            u=search(cn);            scanf("%d",&wei[u]);            while(1)            {                cn[0]=0;//每次都有初始字符串               int d=get2(cn);                if(strlen(cn)==0)break;                v=search(cn);                fa[v]=u;                insert(u,v);                if(0==d)break;            }        }        for(i=0;i<n;i++)        if(fa[i]==-1)          inidfs(i,-1);        for(i=0;i<n;i++)        if(fa[i]==-1)          dfs(i,-1);        for(j=1;j<=n;j++)          cost[j]=eps;        cost[0]=0;ans=eps;        for(i=0;i<n;i++)         if(fa[i]==-1)           for(j=n;j>=0;j--)             for(k=0;k<=j&&k<=son[i];k++)              if(cost[j-k]!=eps)               cost[j]=min(cost[j],cost[j-k]+dp[i][k]);         for(i=m;i<=n;i++)           ans=min(ans,cost[i]);         printf("%d\n",ans);    }    return 0;}



原创粉丝点击