zoukankan      html  css  js  c++  java
  • hdu4966 最小树形图(最少辅导花费)

    题意:
          以一些科目,和辅导班,每个科目最终要求修到某个等级,可以花一定的钱在辅导班把某一科目修到某一等级,进入辅导班的时候会有一个限制,那就是达到他给出的科目和等级限制,比如a b c d m的意思就是科目a必须达到b等级才可以花m钱把科目c修到d等级,最后问把所有科目修到给定的等级要花的最小辅导费用。

    思路:

          我们可以把每一个科目的每一个等级看成一个点,然后根据给定的关系,把等级和等级之间的边和权建立起来,然后再把非0等级建一条当前等级-1的边,费用为0,意思是修了当前等级,之前的等级也算是修完了,最后在虚拟出来一个点,连接所有等级0的点,意思是最开始0等级的已经修完了,然后一遍最小树形图就行了,对于最小树形图,他其实就是在求有向图的最小生成树,用的是 朱-刘 算法(我自己现在还不了解那个算法,只是直接粘模板而已,自己一直感觉不到这个算法的正确性)。


    #include<stdio.h>
    #include<string.h>
    
    
    //******************************************
    const int maxm=2000000;  //边的个数 
    const int maxn=25100;      //点的个数 
    const int inf=0x3f3f3f3f;
    
    typedef struct 
    {
           int u,v,w;
    }EDGE;
    EDGE e[maxm];
    int pre[maxn],id[maxn],vis[maxn],in[maxn];
    typedef struct 
    { 
       int directedMST(int root ,int n ,int m)  
       {  //从0开始用的 0....N,m条边 
           int res=0,nv=n + 1,i;
           while (1)
           {
               for (i=0;i<nv;i++)
               {
                   in[i]=inf;
               }
               for (i=1;i<=m;i++)
               {
                   int u=e[i].u;
                   int v=e[i].v;
                   if (e[i].w<in[v]&&u!=v)
                   {
                       pre[v]=u;
                       in[v]=e[i].w;
                   }
               }
               for (i=0;i<nv;i++)
               {
                   if (i==root)continue;
                   if (in[i]==inf)return -1;
               }
               int cntnode=0;
               memset(id,-1,sizeof(id[0])*(nv+3));
               memset(vis,-1,sizeof(vis[0])*(nv+3));
               in[root]=0;
               for (i=0;i<nv;i++)
               {
                   res+=in[i];
                   int v=i;
                   while (vis[v]!=i&&id[v]==-1&&v!=root)
                   {
                       vis[v]=i;
                       v=pre[v];
                   }
                   if (v!=root&&id[v]==-1)
                   {
                       for (int u=pre[v];u!=v;u=pre[u])
                       {
                           id[u]=cntnode;
                       }
                       id[v]=cntnode++;
                   }
               }
               if (cntnode==0)break;
               for (i=0;i<nv;i++)
               {
                   if (id[i]==-1)id[i]=cntnode++;
               }
               for (i=1;i<=m;i++)
               {
                   int v=e[i].v;
                   e[i].u=id[e[i].u];
                   e[i].v=id[e[i].v];
                   if (e[i].u!=e[i].v)
                   {
                       e[i].w-=in[v];
                   }
               }
               nv=cntnode;
               root=id[root];
           }
           return res;
       }
    }M_Tree;
    //***************************************
    
    
    int sum[55];
    int num[55];
    
    int main ()
    {
        int n ,m ,i ,j;
        int a ,b ,c ,d ,mo;
        M_Tree T;
        while(~scanf("%d %d" ,&n ,&m) && n + m)
        {
           sum[0] = 0;
           for(i = 1 ;i <= n ;i ++)
           {
              scanf("%d" ,&num[i]);
              num[i] ++;
              sum[i] = sum[i-1] + num[i];
           }
           int tt = 0;
           while(m--)
           {
              scanf("%d %d %d %d %d" ,&a ,&b ,&c ,&d ,&mo);
              b++ ,d ++;
              for(int i = sum[a-1] + b ;i <= sum[a] ;i ++)
              {
                 e[++tt].u = i;
                 e[tt].v = sum[c-1] + d;
                 e[tt].w = mo;
               }
           }
           for(i = 1 ;i <= n ;i ++)
           {
              for(j = sum[i-1] + 2 ;j <= sum[i] ;j ++)
              {
                e[++tt].u = j;
                e[tt].v = j-1;
                e[tt].w = 0;
              }
              e[++tt].u = 0;
              e[tt].v = sum[i-1] + 1;
              e[tt].w = 0;
           }
           printf("%d
    ",T.directedMST(0 ,sum[n] ,tt));   
        }
        return 0;
    }
             
           

  • 相关阅读:
    最大子数组求和并进行条件组合覆盖测试
    Ubuntu 16.04 c++ Google框架单元测试
    The directory '/home/stone/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If execu
    Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    个人博客作业三:微软小娜APP的案例分析
    补交 作业一
    补交 作业二:个人博客作业内容:需求分析
    嵌入式软件设计第12次实验报告
    嵌入式软件设计第11次实验报告
    嵌入式软件设计第10次实验报告
  • 原文地址:https://www.cnblogs.com/csnd/p/12062848.html
Copyright © 2011-2022 走看看