【HDU4966】GGS-DDU
题意
有n种科目,每个科目都有一个最高的等级a[i]。开始的时候,每个科目的等级都是0。现在要选择一些课程进行学习使得每一个科目都达到最高等级。这里有m节课可供选择。对于每门课给出L1[i],c[i],L2[i],d[i],money[i],要选择这门课要求科目c[i]的等级不小于L[i],可以使科目d[i]的等级升为L2[i],花费金钱money[i]。请计算最小花费是多少。
数据范围N<=50,M<=2000,sum of a[1] to a[n]不超过500.
分析
最小树形图,要用到朱刘算法。其实。。。我是昨晚在补这道题的时候才去学了一下朱刘算法。。。。。。
朱刘算法学习博客https://blog.csdn.net/txl199106/article/details/62045479
对于这道题我是这么想的,把每个科目的每个等级都拆成点,然后建一个编号为0的点向各个科目等级为0的点连一条权值为0的边。对于每个科目,将他们等级从高到低的点依次连权值为0的点,然后对于每一门课程按照要求连边,权值为这门课程的花费。
建图完成以后,以0点为root跑朱刘算法得到最小树形图,然后这就是答案了。
应该会这个算法就很好做的一道题。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=+;
const int INF=; struct Edge{
int from,to;
long long w;
}edges[maxn];
int sz;
int a[],sum[];
int N,M;
void add_edge(int from,int to,long long w){
++sz;
edges[sz].from=from;edges[sz].to=to;edges[sz].w=w;
}
int pre[maxn];//存储父节点
int vis[maxn];//标记作用
int id[maxn];//id[i]记录节点i所在环的编号
int in[maxn];//in[i]记录i入边中最小的权值
long long zhuliu(int root, int n, int m, Edge *edge)//root根 n点数 m边数
{
long long res = ;
int u, v;
while()
{
for(int i = ; i < n; i++)
in[i] = INF;//初始化
for(int i = ; i <= m; i++)
{
Edge E = edge[i];
if(E.from != E.to && E.w < in[E.to])
{
pre[E.to] = E.from;//记录前驱
in[E.to] = E.w;//更新
}
}
for(int i = ; i <n; i++)
if(i != root && in[i] == INF)
return -;//有其他孤立点 则不存在最小树形图
//找有向环
int tn = ;//记录当前查找中 环的总数
memset(id, -, sizeof(id));
memset(vis, -, sizeof(vis));
in[root] = ;//根
for(int i = ; i <n; i++)
{
res += in[i];//累加
v = i;
//找图中的有向环 三种情况会终止while循环
//1,直到出现带有同样标记的点说明成环
//2,节点已经属于其他环
//3,遍历到根
while(vis[v] != i && id[v] == - && v != root)
{
vis[v] = i;//标记
v = pre[v];//一直向上找
}
//因为找到某节点属于其他环 或者 遍历到根 说明当前没有找到有向环
if(v != root && id[v] == -)//必须上述查找已经找到有向环
{
for(int u = pre[v]; u != v; u = pre[u])
id[u] = tn;//记录节点所属的 环编号
id[v] = tn++;//记录节点所属的 环编号 环编号累加
}
}
if(tn == ) break;//不存在有向环
//可能存在独立点
for(int i = ; i <n; i++)
if(id[i] == -)
id[i] = tn++;//环数累加
//对有向环缩点 和SCC缩点很像吧
for(int i = ; i <= m; i++)
{
v = edge[i].to;
edge[i].from = id[edge[i].from];
edge[i].to = id[edge[i].to];
//<u, v>有向边
//两点不在同一个环 u到v的距离为 边权cost - in[v]
if(edge[i].from != edge[i].to)
edge[i].w -= in[v];//更新边权值 继续下一条边的判定
}
n = tn;//以环总数为下次操作的点数 继续执行上述操作 直到没有环
root = id[root];
}
return res;
} int main(){
while(scanf("%d%d",&N,&M)!=EOF&&N&&M){
sz=;
sum[]=;
for(int i=;i<=N;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i]+;
} int c,L1,d,L2;
long long w;
for(int i=;i<=M;i++){
scanf("%d%d%d%d%lld",&c,&L1,&d,&L2,&w);
/* for(int j=L1;j<=a[c];j++){
add_edge(sum[c-1]+j+1,sum[d-1]+L2+1,w);
}*/
add_edge(sum[c-]+L1+,sum[d-]+L2+,w);
}
for(int i=;i<=N;i++){
add_edge(,sum[i-]+,);
}
for(int i=;i<=N;i++){
for(int j=;j<a[i];j++){
add_edge(sum[i-]+j+,sum[i-]+j+,);
}
}
/*printf("%d\n",sz);
for(int i=1;i<=sz;i++){
printf("%d %d %d\n",edges[i].from,edges[i].to,edges[i].w);
}*/
//cout<<sum[n]<<endl;
long long ans=zhuliu(,sum[N]+,sz,edges);
printf("%lld\n",ans);
}
return ;
}
【HDU4966】GGS-DDU的更多相关文章
- 【OGG】OGG基础知识整理
[OGG]OGG基础知识整理 一.GoldenGate介绍 GoldenGate软件是一种基于日志的结构化数据复制软件.GoldenGate 能够实现大量交易数据的实时捕捉.变换和投递,实现源数据库与 ...
- 【OGG】 RAC环境下管理OGG的高可用 (五)
[OGG] RAC环境下管理OGG的高可用 (五) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道 ...
- 【OGG】RAC环境下配置OGG单向同步 (四)
[OGG]RAC环境下配置OGG单向同步 (四) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的 ...
- 【OGG】OGG简单配置双向复制(三)
[OGG]OGG简单配置双向复制(三) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O ...
- 【OGG】OGG的单向复制配置-支持DDL(二)
[OGG]OGG的单向复制配置-支持DDL(二) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的 ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
随机推荐
- PhotoShop脚本指南
Photoshop脚本语言 Photoshop支持三种脚本语言:AppleScript,VBScript,JavaScript.其中AppleScript为苹果系统,VBScript为Windows操 ...
- mysql 存储过程查询语句
可以用 命令"show PROCEDURE status"查看所有的存储过程或检索系统表"mysql.proc"来查询已有的存储过程.例如:用show PROC ...
- [转载] FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- SpringMVC集成rabbitMQ
Maven引入相关jar <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-c ...
- MDK中STM32使用Printf函数详细解析【转载】
在用MDK调试STM32板子串口时,为了方便串口调试,调用了printf()函数,用Keil仿真是,串口不能正确的输出,软件仿真时,总是卡在那 里.有点纳闷,然后调用USART_SendData()函 ...
- 三种实现Ajax的方式
本文主要是比较三种实现Ajax的方式 1. prototype.js 2. jquery1.3.2.min.js 3. json2.js Java代码 收藏代码 后台处理程序(Servlet),访问路 ...
- JMeter使用经历
JMeter是Apache大树下的又一个果实,是一个压力测试工具,因为使用方便又开源免费,也被用来做功能测试.项目里也是拿JMeter来做功能性的接口自动化测试.这里大概说明下怎么用. 首先还是先下载 ...
- PhysicalDrive
由于"\"是C/C+中转义符, "\\\\.\\"就相当于\\.\ 在Windows中 \\.\ 前缀用于标识设备,其中的"."表示本地计算 ...
- 1133 Splitting A Linked List
题意:把链表按规则调整,使小于0的先输出,然后输出键值在[0,k]的,最后输出键值大于k的. 思路:利用vector<Node> v,v1,v2,v3.遍历链表,把小于0的push到v1中 ...
- 生成器+列表生成式,生成器可以节省内存,随时调取函数运行,以及实现多线程运行函数,__next__()和.send(参数)的区别,a,b=b,a+b其实是元祖的用法,出现异常状态用try...except StopIteration来处理
列表生成式:是代码更简洁. 也可以是函数,比如func(i) 生成器:generator 列表生成式,是中括号,改成小括号,就是生成器: 如果你用列表生成式,生成一亿个数据:这里会卡好久,会生成一亿个 ...