/*

辛辛苦苦调试半天,

过了样例,竟然没有ac!!

网上对比了ac代码,感觉添加一个虚根就能ac

但是想不明白为什么

*/

/*

第二天想了下,知道了为什么wa:因为从等级0连到其他课程等级i的不止一门课,如果不加虚根,仅仅是通过判断L1[i]==0来决定根节点显然是会错的

添加根节点能保证生成的是最小树形图

*/

我的代码

/*
hdu4966
第i门课从0到a[i]个等级,从最开始所有课都是0级,目标所有课到最高级
M条路,如果第i门课达到L1[i],那么通过M后,第j门课到达L2[i]
N,M
a[i] .. a[N]
接下来M行c[i], L1[i], d[i], L2[i], money[i]
边权当然是money,每门课拆成a[i]个等级(500个点)
每门课的a[i]到a[i]-1连一条权值为0的边
增加一个超级源点,和每门课level 0连在一起
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 505
#define INF 0x3f3f3f
using namespace std;
struct Edge{int u,v,cost;
}edge[MAXN*MAXN];
int a[MAXN];//等级
int V[MAXN][MAXN];//点集
int c[MAXN],L1[MAXN],d[MAXN],L2[MAXN],money[MAXN];
int pre[MAXN],id[MAXN],vis[MAXN],in[MAXN];
int zhuliu(int root,int n,int m){int res=0;int u,v;while(1){for(int i=0;i<n;i++)in[i]=INF;for(int i=0;i<m;i++)if(edge[i].u!=edge[i].v && edge[i].cost<in[edge[i].v]){pre[edge[i].v]=edge[i].u;in[edge[i].v]=edge[i].cost;}for(int i=0;i<n;i++)if(i!=root && in[i]==INF)return -1;int tn=0;memset(id,-1,sizeof id);memset(vis,-1,sizeof vis);in[root]=0;for(int i=0;i<n;i++){res+=in[i];v=i;while(v!=root && id[v]==-1 && vis[v]!=i){vis[v]=i;v=pre[v];}if(id[v]==-1 && v!=root){for(int u=pre[v];u!=v;u=pre[u])id[u]=tn;id[v]=tn++;}}if(tn==0)break;for(int i=0;i<n;i++)if(id[i]==-1)id[i]=tn++;for(int i=0;i<m;i++){//第四步,更新一次边集 int u=edge[i].u;int v=edge[i].v;edge[i].u=id[u];edge[i].v=id[v];if(id[u] != id[v])edge[i].cost-=in[v]; }n=tn;root=id[root];        }return res;
}
int totm;
void addedge(int u,int v,int w){edge[totm].u=u;edge[totm].v=v;edge[totm].cost=w;totm++;
}
int main(){int n,m,totn;while(scanf("%d%d",&n,&m) && n && m){totn=totm=0;memset(V,0,sizeof V);for(int i=1;i<=n;i++){scanf("%d",&a[i]);for(int j=0;j<=a[i];j++){V[i][j]=totn++; if(j!=0)addedge(V[i][j],V[i][j-1],0);}}int sum=0,root=0;for(int i=1;i<=m;i++){scanf("%d%d%d%d%d",&c[i],&L1[i],&d[i],&L2[i],&money[i]);if(L1[i]==0)root=c[i];addedge(V[c[i]][L1[i]],V[d[i]][L2[i]],money[i]);sum+=money[i];}if(root==0){printf("-1\n");continue;}int ans=zhuliu(root,totn,totm);printf("%d\n",ans);}return 0;
}

ac代码

#include <cstdio>
#include <cstring>
#include <iostream>using namespace std;const int maxn = 555, maxm = 500 * 2000, inf = 1e9;struct Edge{int u, v, w;Edge(){}Edge(int u, int v, int w):u(u), v(v), w(w){}
}e[maxm];
int ec;
int lev[55], begid[55], endid[55];
int N;int mincost[maxn], pre[maxn];
bool makeMin(int root){for(int i = 1; i <= N; i++) mincost[i] = inf;for(int i = 0; i < ec; i++){if(e[i].u == e[i].v) continue;int v = e[i].v;if(mincost[v] > e[i].w){mincost[v] = e[i].w;pre[v] = e[i].u;}    }for(int i = 1; i <= N; i++){if(i == root) continue;if(mincost[i] == inf) return false;}return true;
}int vis[maxn];
int id[maxn];
bool existCircle(int root, int &res){memset(vis, -1, sizeof(vis));memset(id, -1, sizeof(id));int ind = 1;mincost[root] = 0;for(int i = 1; i <= N; i++){int v = i;res += mincost[i];while(vis[v] != i && v != root && id[v] == -1) {vis[v] = i, v = pre[v];}if(v != root && id[v] == -1){for(int u = pre[v]; u != v; u = pre[u]) id[u] = ind;id[v] = ind++;}}if(ind == 1) return false;for(int i = 1; i <= N; i++)if(id[i] == -1) id[i] = ind++;N = ind - 1;return true;
}void update(){for(int i = 0; i < ec; 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) continue;e[i].w -= mincost[v];            }
}int DMST(int root){int res = 0;while(1){if(!makeMin(root)) return -1;if(!existCircle(root, res)) return res;update();root = id[root];}return -1;
}int main(){
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);int n, m;while(scanf("%d%d", &n, &m), n&&m){for(int i = 1; i <= n; i++) scanf("%d", lev+i);    lev[0] = 1, begid[0] = 0;    for(int i = 1; i <= n; i++) begid[i] = begid[i-1] + lev[i-1] + 1;N = begid[n] + lev[n];        int c, l, d, r, w;int root = 1;ec = 0;for(int i = 1; i <= n; i++)e[ec++] = Edge(root, begid[i], 0);for(int i = 1; i <= n; i++){for(int j = 1; j <= lev[i]; j++){int u = begid[i] + j, v = u - 1;e[ec++] = Edge(u, v, 0);}}for(int i = 0; i < m; i++){scanf("%d%d%d%d%d", &c, &l, &d, &r, &w);int v = begid[d] + r;for(int j = l, u = begid[c] + l; j <= lev[c]; u++, j++){e[ec++] = Edge(u, v, w);    }}    int ans = DMST(root);if(~ans) printf("%d\n", ans);else puts("-1");}return 0;
}

转载于:https://www.cnblogs.com/zsben991126/p/9801029.html

hdu4966 最小树形图+虚根相关推荐

  1. HDU 4009 Transfer water (最小树形图+虚根)

    题意:有一个村庄需要修建供水系统.每户居民的房子都有一个三维坐标,每户居民可以选择自己挖井或者从其他居民家里引水.挖水井和引水分别需要花费不同的钱.每户居民有一个意愿表,只愿意对表内的居民家供水.最后 ...

  2. HDU 2121 Ice_cream’s world II (最小树形图+虚根)

    题意:有n个点(0~n-1),m条有向边,问以哪个点作为起点使得最小生成树的权值最小,如果可以构成输出权值和顶点编号,否则输出impossible. 题解:最小树形图+虚根 还好做了这题,板子有点问题 ...

  3. hdu 2121 最小树形图 +虚根

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2121 题意: n个城市,m条单向边,每条边都有一个权值,现在要你求出这样一个节点,由这个节点出发能走遍 ...

  4. hdu4966 最小树形图(最少辅导花费)

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

  5. HDU 2121 Ice_cream’s world II(最小树形图+虚根)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2121        题意是有n个点(0--n-1),m条有向边,问以那个点作为起点使得最小生成树的权值 ...

  6. 最小树形图-hdu4966

    https://vjudge.net/contest/311526#problem/G 大意:给定n(50)门属性,每门属性有a[i](500)个级别,同时有M(2000)门课程,参加j号课程需要c属 ...

  7. hdu-4966 GGS-DDU 最小树形图

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4966 题意: 给你n门课的最高等级及m条升级方法,开始时你每门课的等级都在等级0,升级方法的5个参数代 ...

  8. 【转】【最小树形图】有向图的最小生成树【朱刘算法】

    这篇文章挺好的.每行还有注释QAQ,kuangbin的模板里并没有万能节点: 万能节点好像是在不定根的时候的拓展. 要点: 1.求所有边权和sum; 2.以0点为万能节点向所有点建一条权值为sum的边 ...

  9. 最小树形图(朱刘算法)模板

    最小树形图:有向图,求以某个确定的点为根的外向最小生成树. 最小树形图朱刘算法:https://www.luogu.com.cn/blog/i207M/shu-xing-tu-shu-liu-suan ...

最新文章

  1. Day2_and_Day3 文件操作
  2. SimpleDelegate 委托
  3. python在会计工作中的应用-python有什么用(会计专业)
  4. mixin模式 python_Python中的mixin模式
  5. VTK:多数据点用法实战
  6. 2014年第五届蓝桥杯C/C++ A组国赛 —— 第四题:排列序数
  7. 快速解析大xml报文
  8. React Router入门指南
  9. js中window的属性
  10. php查netstat,Netstat命令详解
  11. Windows操作系统架构梳理
  12. 计算机基础知识2019题库,2019年计算机基础考试题库(含答案)全
  13. 微信支付测试商户号开发必备(有效的)
  14. napi娃娃_第二十九章 干妈
  15. 高盛发布区块链报告:从理论到实践(中文版)三
  16. css画心形原理,如何用 css 画一个心形
  17. BOOT模式选择启动、Error -6311 PRSC modulefailedtowritetoa register。
  18. 数字高程模型(DEM)—知识汇总
  19. 分水岭:知识的深度拓展
  20. 图解Transformer

热门文章

  1. 开发实战:基于深度学习+maven+SSM+EasyUI的高校共享汽车管理系统(一)
  2. wd移动硬盘测试软件,WD西数 MY Passport移动硬盘拆解评测
  3. 什么是 95计费方式
  4. 图灵的文章“Computing machinery and intelligence”译文
  5. 你知道吗?申报深圳市专精特新企业必须先申报创新型中小企业!
  6. 90后,第一批接棒白酒的“年轻人”
  7. phpmyadmin 修改记录(不断更新)
  8. inner join 和outer join的区别
  9. 重要公告|Moonriver成功续约Kusama平行链插槽租赁期
  10. [转载] 老鼠夹的寓言