cogs1355. 读书 x

1355. 读书

★   输入文件:reading.in   输出文件:reading.out   简单对比
时间限制:1 s   内存限制:128 MB

【题目描述】

放暑假了,CHH想趁假期提高一下自己的计算机水平,于是他从学校图书馆借了N本计算机科学方面的书,这N本书的编号依次为0~N-1。

读完第i本书,CHH需要花费time[i]分钟,但是有一些书的内容是相近的,如果第i本书与第j本书内容相近,那么如果CHH读完了第i本书,再读第j本书的时候只需要floor(time[j]/2)分钟的时间即可(其中floor()表示对括号中的式子进行下取整);当然,如果CHH先读完了第j本书,那么再读第i本书的时候只需floor(time[i]/2)的时间。现在你的任务是告诉CHH,他最少可以用多少分钟读完这N本书。

【输入格式】

第一行有两个整数N(0<=N<=100)和M(0<=M<=N(N-1)/2)。N为书的总数,有M对书内容相近。

接下来有N行,分别表示time[0],time[1],...及time[N-1],(1<=time[i]<=10^5)。

再接下来有M行,每行有两个整数(i,j),表示第i本书与第j本书内容相近。

输入文件以N=0,M=0表示结束。

【输出格式】

对于每组测试数据,输出仅一行,即最少时间。

【样例输入】

2 1
6
10
0 1
3 2
1
2
3
0 1
1 2
3 1
2
4
6
0 1
0 0 

【样例输出】

11
3
10

【提示】

对于第一组数据,如果CHH读的顺序为(0,1),则总的时间为6+10/2=11,如果读的顺序为(1,0),则总的读书时间为10+6/2=13.

思路:

  题目中提及:

     2本书之间可能内容相近,所以我们可以采用并查集,然后贪心选一个集合中用时最小的书,剩下的除2加入总时间即可。

     故我们可以用kruskal来做这道题

坑点:

  1)若出现m==0但是n!=0,此时不要退出程序!!!

  2)要从0开始进行标号

上代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

const int N = 110;
const int M = 5050;
int n,m,ans;
int t[N],dad[N];
bool vis[N];

int getdad(int x)
{return dad[x] == x ? x : dad[x] = getdad(dad[x]);}

void kruskal()
{
    while(true)
    {
        int flag=-1;
        int tmp[200]={0},cnt=0;
        for(int i=0;i<n;i++)
        {
            if(flag==-1 && !vis[i])
            {
                vis[i]=true;
                flag=getdad(i);
                tmp[++cnt]=t[i];
            }
            else if(flag!=-1 && !vis[i] && getdad(i)==flag)
            {
                vis[i]=true;
                tmp[++cnt]=t[i];
            }
        }
        if(!cnt)
        {
            cout<<ans<<endl;
            break;
        }
        sort(tmp+1,tmp+1+cnt);
        ans+=tmp[1];
        for(int i=2;i<=cnt;i++)
            ans+=floor(tmp[i]>>1);
    }
}

void chu()
{
    ans=0;
    memset(t,0,sizeof(t));
    memset(vis,false,sizeof(vis));
    memset(dad,0,sizeof(dad));
}

int main()
{
    freopen("reading.in","r",stdin);
    freopen("reading.out","w",stdout);
    while(cin>>n>>m)
    {
        if(n==0 && m==0)
            break;
        chu();
        for(int i=0;i<n;i++)
            cin>>t[i],dad[i]=i;
        for(int i=0,u,v;i<m;i++)
        {
            cin>>u>>v;
            int f1=getdad(u),f2=getdad(v);
            if(f1!=f2)
                dad[f1]=f2;
        }
        kruskal();
    }
    return 0;
}
时间: 2024-10-07 23:57:14

cogs1355. 读书 x的相关文章

《C#图解教程》读书笔记之三:方法

本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.方法那些事儿 (1)方法的结构:方法头-指定方法的特征,方法体-可执行代码的语句序列: (2)方法的调用:参数.值参数.引用参数.输出参数.参数数组: ①参数: 形参-本地变量,声明在参数列表中:形参的值在代码开始之前被初始化: 实参-实参的值用于初始化形参: ②值参数: 为形参在栈上分配内存,将实参的值复制到形参: ③引用参数: 不为形参在栈上分配内存,形参的参数名作为实参变量的别名指向同一位置,必须使用ref关

《C#图解教程》读书笔记之五:委托和事件

本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.委托初窥:一个拥有方法的对象 (1)本质:持有一个或多个方法的对象:委托和典型的对象不同,执行委托实际上是执行它所"持有"的方法.如果从C++的角度来理解委托,可以将其理解为一个类型安全的.面向对象的函数指针. (2)如何使用委托? ①声明委托类型(delegate关键字) ②使用该委托类型声明一个委托变量 ③为委托类型增加方法 ④调用委托执行方法 (3)委托的恒定性: 组合委托.为委托+=增加

机电传动控制读书笔记二(书本内容)

读书内容:<自动化技术中的进给电气传动>第一章的第1.3节:<控制系统指南>的第一章和第二章:Plecs仿真实验结果. 知识要点: <自动化技术中的进给电气传动> 1.对于线性传递环节的实际系统,其输入量的微分的最高阶数m不大于输出量的最高阶数n, 2.在不可调传动系统情况下,在系统稳定状态下,一个接入的负载转矩ML会产生一个角速度为wM的固定偏差.而且在起始t=0的情况下,发生了ML的跃变.并有如下规律: n=m:当出现一个输入量跃变时,输出量也同样出现一个跃变. n

《七周七数据库》读书分享

# 七周七数据库 读书分享会第一期 2017.02.12 <七周七数据库> - Eric Redmond ## 预备知识 ACID:原子 一致 隔离 持久 CAP原则:一致性 可用性 分区容错性,在分布式环境下,至多只能同时满足其二 "小明,你的数据库作业呢?""我可以今天提交一半的作业,或者明天提交全部的作业,但无法在今天提交全部的作业.""...小明你给我滚出去!" 小知识点: * 原子性:原子性代表中间状态的透明性,想象从a账户

2017除夕夜的感悟:学习工作不分家,工作生活不分家,读书用兵不分家

学习工作不分家 = 学习的低效,就是因为只是完成任务,在被动的学习,没有避免重复训练(最开始还是需要有一定的重复量,以后再重复就相当于十年工作经验等于别人一年了.因为已经很熟了,再熟练也是没有长进),要刻意检查自己的效果.寻求纠正. 工作生活不分家 = 对于我的工作来说,需要无时无刻的学习,在家学还是在公司学,对我个人的效果来说是一样的,既然自己想成为一个高手,就要努力一点.随时随地学.另外,我个人有创业机会,更要研究市场,以及自己提前做一些辅助性的工作. 读书用兵不分家 = 从书中学习历史经验

装X之读书

0.读书又记不住...读过又有什么用...读万卷书 == 读0卷书 ?? 1.额.读书不是记住的,毕竟哪里有这么多过目不忘的天才...要理解书中的内容...理解... 2.还是要记的,但是要理解的基础上记住...

《Effective C++》读书笔记汇总

我之前边读<Effective C++>边写下每个条款的读书笔记,这一版是C++11之前的版本.这里我将每个条款令我印象深刻的点小结一下. 1.C++包括:Plain C(面向过程).OOP(面向对象).模板(泛型和模板元编程).STL(C++标准库). 2.用inline.enum.const代替#define.#define定义的宏,一旦复杂起来,高手都很难掌控.不要带入C的习惯. 3.灵活使用const前缀.不需要进行改变的数据加上const前缀.指针的const前缀有两种形式,cons

【读书笔记】《Linux内核设计与实现》内核同步介绍&内核同步方法

简要做个笔记,以备忘. 需同步的原因是,我们并发访问了共享资源.我们将访问或操作共享资源的代码段称"临界区",如果两个执行线程处于同一临界区中同时执行,称"竞争条件".这里术语执行线程指任何正在执行的代码实例,如一个在内核执行的进程.一个中断处理程序或一个内核线程. 举个简单例子,i++操作.该操作可以转换为下面的机器指令序列: 1.得到当前变量i的值,并保存到一个寄存器. 2.将寄存器的值加1. 3.将i的新值写回到内存中. 当两个线程同时进入这个临界区,若i初值

鸟哥的Linux私房菜 基础学习篇读书笔记(7):Linux文件与目录管理

这一章主要讲述的是如何操作与管理Linux系统中的文件和目录,主要包括目录间的切换,目录的创建与删除,文件的创建与删除,文件的查找,文件内容的查看等等. 前一章中已经讲过相对路径以及绝对路径,绝对路径就是指从根目录("/")开始写起的路径名,而相对路径绝不会由根目录开始写起,相反,相对路径是相对于当前工作目录的路径名.Linux操作系统中有几个特殊的目录: . 代表此层目录: .. 代表上一层目录: - 代表前一个工作目录: ~ 代表当前用户身份所在的主文件夹: ~account 代表