将每门课等级拆成0,1,2,3...a[i]个点,对每个等级大于0的点向它低一级连边,权值为0【意思是,若修了level k,则level(0~k)都当做修了】
将输入的边建边,权值为money[i]。
建立根节点,向每个level 0的点连边,权值为0【因为初始level 0的都修了】
由于题目要求每门课都必须达到最大level,也就是对应图中根节点能到达所有点,问题就变成了求无向图的最小生成树。
#include
#include
#include
#include
#include
using namespace std; #define INF 0x3FFFFFF #define MAXN 5555 struct edge { int u,v,w; }e[9999999]; int n,en; int pre[MAXN],in[MAXN],id[MAXN],vis[MAXN]; void add(int u,int v,int w) { e[en].u=u; e[en].v=v; e[en++].w=w; } int zl(int root ,int vn) { int ans=0; int cnt; while(1) { for(int i=0;i
e[i].w && e[i].u!=e[i].v) { pre[e[i].v]=e[i].u; in[e[i].v]=e[i].w; } } in[root]=0; pre[root]=root; for(int i=0;i
%d\n",pres[i-1]+id+1,pres[i-1]+id); } add(s,pres[i-1]+1,0); // printf("%d -> %d\n",pres[i-1]+a[i]+1,t); // printf("%d -> %d\n",s,pres[i-1]+1); } for(int i=1;i<=m;i++) { scanf("%d%d%d%d%d",&x,&y,&b,&c,&d); add(pres[x-1]+y+1,pres[b-1]+c+1,d); // printf("%d -> %d\n",pres[x-1]+y+1,pres[b-1]+c+1); } int tmp=zl(0,t); if(tmp<0) puts("-1"); else printf("%d\n",tmp); } return 0; }