首页 > 代码库 > HDU:GGS-DDU

HDU:GGS-DDU

HDU:GGS-DDU

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4966

题目大意:有$n$个课程,初始都在等级$0$,每个课程需要达到等级$a[i]$.满足$x$课程等级大于等于$dx$时,可花费$w$使得$y$课程等级达到$dy$,求最少需要多少钱?

最小树形图

一个有向图若存在从某个点开始的到达所有的的一个最小生成树,则它就是最小树形图。

引自http://www.cnblogs.com/vongang/archive/2012/07/18/2596851.html

为每个课程的每个等级设置结点,若$x$课程等级大于等于$dx$时,可花费$w$使得$y$课程等级达到$dy$,则

建一条从$x$课程等级等于$dx$的点到$y$课程等级等于$dy$的点,长度为$w$的有向边.

因为课程等级是向下兼容的,即等级高的点可以无消耗达到等级低的点,故每个课程等级高的点向等级低的点建长度为$0$的边.

从而,求最小代价转化为了求整张图的最小树形图(若某课程达到最高等级那么一定可以达到较低等级).

求最小树形图的复杂度为$O(VE)$.

代码如下:

  1 #include <cstdio>  2 #include <vector>  3 #include <cstring>  4 #define N 55  5 #define MAXN 25055  6 #define MAXM 30000  7 using namespace std;  8 const int inf=10000000;  9 int n,m,a[N]; 10 struct ZL{ 11     int n,m; 12     int pre[MAXN],id[MAXN],vis[MAXN]; 13     int inEdge[MAXN]; 14     struct Edge{ 15         int u,v; 16         int w; 17     }edge[MAXM]; 18     void init(int n_){ 19         n=n_;m=0; 20     } 21     void addedge(int u,int v,int w){ 22         edge[m].u=u; 23         edge[m].v=v; 24         edge[m].w=w; 25         m++; 26     } 27     int Directed_MST(int root){ 28         int ans=0,u,v; 29         while(1){ 30             for(int i=0;i<n;++i) 31                 inEdge[i]=inf; 32             for(int i=0;i<m;++i){ 33                 u=edge[i].u; 34                 v=edge[i].v; 35                 if(edge[i].w<inEdge[v]&&u!=v) { 36                     pre[v]=u; 37                     inEdge[v]=edge[i].w; 38                 } 39             } 40             for(int i=0;i<n;++i) 41                 if(i!=root&&inEdge[i]==inf) 42                     return -1; 43             int cnt=0; 44             memset(id,-1,sizeof(id)); 45             memset(vis,-1,sizeof(vis)); 46             inEdge[root]=0; 47             for(int i=0;i<n;++i) { 48                 ans+=inEdge[i]; 49                 int cur=i; 50                 while(vis[cur]!=i&&cur!=root&&id[cur]==-1) { 51                     vis[cur]=i; 52                     cur=pre[cur]; 53                 } 54                 if(cur!=root&&id[cur]==-1) { 55                     v=pre[cur]; 56                     while(v!=cur) { 57                         id[v]=cnt; 58                         v=pre[v]; 59                     } 60                     id[cur]=cnt++; 61                 } 62             } 63             if(cnt==0) 64                 return ans; 65             for(int i=0;i<n;++i) 66                 if(id[i]==-1) 67                     id[i]=cnt++; 68             for(int i=0;i<m;++i){ 69                 u=edge[i].u; 70                 v=edge[i].v; 71                 edge[i].u=id[u]; 72                 edge[i].v=id[v]; 73                 if(id[u]!=id[v]) 74                     edge[i].w-=inEdge[v]; 75             } 76             n=cnt; 77             root=id[root]; 78         } 79         return ans; 80     } 81 }gao; 82 int main(void){ 83     while(~scanf("%d%d",&n,&m)){ 84         if(n==0&&m==0)break; 85         a[0]=1; 86         for(int i=1;i<=n;++i){ 87             scanf("%d",&a[i]); 88             a[i]+=a[i-1]+1; 89         } 90         gao.init(a[n]); 91         for(int i=1;i<=n;++i){ 92             gao.addedge(0,a[i-1],0); 93             for(int j=a[i-1];j<a[i]-1;++j) 94                 gao.addedge(j+1,j,0); 95         } 96         for(int i=0;i<m;++i){ 97             int x,dx,y,dy,w; 98             scanf("%d%d%d%d%d",&x,&dx,&y,&dy,&w); 99             gao.addedge(a[x-1]+dx,a[y-1]+dy,w);100         }101         printf("%d\n",gao.Directed_MST(0));102     }103 }

 

HDU:GGS-DDU