Description

Farmer John's family pitches in with the chores during milking, doing all the chores as quickly as possible. At FJ's house, some chores cannot be started until others have been completed, e.g., it is impossible to wash the cows until they are in the stalls. 



Farmer John has a list of N (3 <= N <= 10,000) chores that must be completed. Each chore requires an integer time (1 <= length of time <= 100) to complete and there may be other chores that must be completed before this chore is started. We will call these
prerequisite chores. At least one chore has no prerequisite: the very first one, number 1. Farmer John's list of chores is nicely ordered, and chore K (K > 1) can have only chores 1,.K-1 as prerequisites. Write a program that reads a list of chores from 1
to N with associated times and all perquisite chores. Now calculate the shortest time it will take to complete all N chores. Of course, chores that do not depend on each other can be performed simultaneously.

Input

* Line 1: One integer, N 



* Lines 2..N+1: N lines, each with several space-separated integers. Line 2 contains chore 1; line 3 contains chore 2, and so on. Each line contains the length of time to complete the chore, the number of the prerequisites, Pi, (0 <= Pi <= 100), and the Pi
prerequisites (range 1..N, of course). 

Output

A single line with an integer which is the least amount of time required to perform all the chores. 

       原题很简单,就是给定N个任务的时间和每个任务的前驱,求最短完成时间。
       初步研究,此题可以用最长路或是拓扑图来求解。

        vijos上有一道“休息中的小呆”,原理和此类似,然而那儿N<=100,N^3也绰绰有余,我就用floyd算法求出最长路并记录。然而现在的N<=10000,就连N^2也很危险。

        第一次,我打算也是用最长路求解。咨询过鼎神,目前只有SPFA可以有效处理最长路问题。方法就是把每条边的权值取相反数并做一遍最短路,答案再取相反数。因为N有10000而边数不知道,只好开一个边表记录。

代码一(SPFA最长路+边表优化)
#include<stdio.h>
#include<cstring>
using namespace std;
const long maxn=10001;const long INF=1;
bool flag[maxn];long cnt,i,n,j,xx,time,y,h,t,go,now,ans,tong;
long dis[maxn],begin[maxn],end[maxn],x[200*maxn];
struct arr{long l,r,s,next;}a[200*maxn];
void make_up(long l,long r,long v)
{
  a[++cnt].l=l;a[cnt].r=r;a[cnt].s=-v;a[cnt].next=-1;
  if (begin[l]==0) {begin[l]=cnt;end[l]=cnt;}
  else {a[end[l]].next=cnt;end[l]=cnt;}
}
int main()
{
  //freopen("chores.in","r",stdin);freopen("chores.out","w",stdout);
  scanf("%ld",&n);
  for (i=1;i<=n;i++)
  {
    scanf("%ld",&time);
    scanf("%ld",&xx);
    for (j=1;j<=xx;j++)
    {
      scanf("%ld",&y);
      make_up(y,i,time);
    }
    if (xx==0) make_up(0,i,time);
  }
  memset(flag,0,sizeof(flag));memset(dis,INF,sizeof(dis));
  h=0;t=1;x[1]=0;dis[0]=0;flag[0]=true;
  while (h<t)
  {
     now=x[++h];if (begin[now]==0) continue;i=begin[now];
     while (true)
     {
       go=a[i].r;
       if (dis[now]+a[i].s<dis[go])
       {
         dis[go]=dis[now]+a[i].s;
         if (!flag[go])
         {
           flag[go]=true;
           x[++t]=go;
         }
       }
       if (a[i].next==-1) break;i=a[i].next;
     }
     flag[now]=false;
  }
  for (i=1;i<=n;i++)
    if (-dis[i]>ans) ans=-dis[i];

  printf("%ld",ans);
  //scanf("%ld",&n);
  return 0;
}

然而交了之后一直TLE,自己下了个数据,发现最后一个点大概要13s左右!想不到在稠密图里,SPFA的效率又如此之低!(边表的常数又很大)无论怎么优化都不行!

       
       最后只能请教互联网了,没想到,其他大牛的代码如此简单!他们用了近似DP的算法!

代码二(据网上思路改编代码)
#include<stdio.h>
#include<cstring>
using namespace std;
long f[10001],n,i,j,max,ans,xx,y;
int main()
{
  //freopen("chores.in","r",stdin);freopen("chores.out","w",stdout);
  scanf("%ld",&n);
  for (i=1;i<=n;i++)
  {
    scanf("%ld",&f[i]);
    scanf("%ld",&xx);max=0;
    for (j=1;j<=xx;j++)
    {
      scanf("%ld",&y);
      if (f[y]>max) max=f[y];
    }
    f[i]+=max;
    if (f[i]>ans) ans=f[i];
  }
  printf("%ld",ans);
  //scanf("%ld",&n);
  return 0;
}

然而仔细一想,我发现他们只是钻了一个数据的漏洞——刚好数据的前后关系是由小到大的。思考了很长时间,我研究出了一个更加高级的算法——记忆化深搜+边表优化!


代码三(最终AC的代码)
#include<stdio.h>
#include<cstring>
using namespace std;
const long maxn=10001;const long INF=1;
long time[maxn],dp[maxn],begin[maxn],end[maxn],cnt,j,n,i,x,y,ans;
struct arr{long l,r,next;}a[200*maxn];
void make_up(long l,long r)
{
  a[++cnt].l=l;a[cnt].r=r;a[cnt].next=-1;
  if (begin[l]==0) {begin[l]=cnt;end[l]=cnt;}
  else {a[end[l]].next=cnt;end[l]=cnt;}
}
long go(long k)
{
  if (dp[k]>0) return dp[k];
  long now=begin[k];
  while (now>0)
  {
    long temp=go(a[now].r);
    dp[k]=(temp>dp[k])?temp:dp[k];
    now=a[now].next;
  }
  dp[k]+=time[k];
  return dp[k];
}
int main()
{
  //freopen("chores.in","r",stdin);freopen("chores.out","w",stdout);
  scanf("%ld",&n);
  for (i=1;i<=n;i++)
  {
    scanf("%ld",&time[i]);
    scanf("%ld",&x);
    for (j=1;j<=x;j++)
    {
      scanf("%ld",&y);make_up(i,y);
    }
    if (x==0) dp[i]=time[i];
  }
  for (i=1;i<=n;i++)
  {
    long temp=go(i);
    ans=(temp>ans)?temp:ans;
  }
  printf("%ld",ans);
  //scanf("%ld",&n);
  return 0;
}

希望众神牛看到后能够留言指导!


usaco 2002 月赛 Chores 题解的更多相关文章

  1. usaco 2002 月赛 Fiber Communications 题解

    Description Farmer John wants to connect his N (1 <= N <= 1,000) barns (numbered 1..N) with a ...

  2. POJ1944 Fiber Communications (USACO 2002 February)

    Fiber Communications 总时间限制:  1000ms 内存限制:  65536kB 描述 Farmer John wants to connect his N (1 <= N ...

  3. csu-2018年11月月赛Round2-div1题解

    csu-2018年11月月赛Round2-div1题解 A(2191):Wells的积木游戏 Description Wells有一堆N个积木,标号1~N,每个标号只出现一次 由于Wells是手残党, ...

  4. csu-2018年11月月赛Round2-div2题解

    csu-2018年11月月赛Round2-div2题解 A(2193):昆虫繁殖 Description 科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强.每对成虫过x个月产y对卵,每对 ...

  5. usaco 2008 月赛 lites 开关灯 题解

      题目:     Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是 牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每一 ...

  6. USACO全部月赛及GateWay数据

    月赛: 以07年open为例,网站如下 http://contest.usaco.org/OPEN07 其他的格式是http://contest.usaco.org/月份(月份的英文前三位,比如1月是 ...

  7. USACO Section 1.3 题解 (洛谷OJ P1209 P1444 P3650 P2693)

    usaco ch1.4 sort(d , d + c, [](int a, int b) -> bool { return a > b; }); 生成与过滤 generator&& ...

  8. 洛谷10月月赛II题解

    [咻咻咻] (https://www.luogu.org/contestnew/show/11616) 令人窒息的洛谷月赛,即将参加NOIp的我竟然只会一道题(也可以说一道也不会),最终145的我只能 ...

  9. BZOJ Lydsy5月月赛 ADG题解

    题目链接 BZOJ5月月赛 题解 好弱啊QAQ只写出三题 A 判断多干个数乘积是否是某个数的倍数有很多方法,比较常用的是取模,但这里并不适用,因为模数不定 会发现数都比较小,所以我们可以考虑分解质因子 ...

随机推荐

  1. VUE依赖webpack分别给开发环境和生产环境配置不同的常量值并在项目中动态引用

    当在开发和产品上线的时候,我们经常会遇到在同一个地方由于环境的不同而地址也不同的情况,这时候如果在代码中将该地址写死,那势必会造成上线时手动改动,多人开发及多处使用该地址难以维护等一系列问题,为避免这 ...

  2. 《一起》Alpha版软件使用说明

    1.引言 1.1编写目的 本手册是软件工程概论团队项目<一起>的Alpha版使用说明,面向的对象群体为全校师生. 1.2项目背景 本项目由<软件工程概论>课程需求创建,软件由S ...

  3. 使用 after 伪类清除浮动

    以前清除浮动的时候总是在想要清除浮动的元素后面添加 <div style="clear:both;"></div> 或者写在br标签里面来解决,但这样会增加 ...

  4. java中的中文参数存到数据库乱码问题

    关于java中的中文参数乱码问题,遇见过很多,若开发工具的字符集环境和数据库的字符集环境都一样,存到数据库中还是乱码的话,可以通过以下方法解决: 用数据库客户端检查每个字段的字符集和字符集校对和这个表 ...

  5. iHover – 30+ 纯 CSS3 实现的超炫的图片悬停特效

    iHover 是一个令人印象深刻的图片悬停效果集合,完全基于 CSS3 实现,无依赖,能够搭配 Bootstrap 3 很好地工作.基于 SCSS 技术构建(包括文件),便于修改变量.有模块化的代码, ...

  6. 【源码分享】jquery+css实现侧边导航栏

    jquery+css实现侧边导航栏 最近做项目的时候,突然想用一个侧边导航栏,网上找了几个插件,有的太丑而且不太符合我的预期.与其修改别人的代码,不如自己来写一个了.废话不多说先上图,感兴趣的请继续看 ...

  7. 请教 C# 异步 async await 问题

    各位园友,之前对C#异步只是肤浅了解,请教一个具体问题. 需求: 前台会发送一个Array,这个数组都是 id的集合,比较大.分两步,首先保存这些id,然后去调用异步方法. 可以正常返回json,也可 ...

  8. Java基础知识总结之IO流

    理解Java的IO流 流(Stream)的概念:程序与数据来源之间的桥梁 流的分类 按流的方向来分(从程序所在的内存的角度来看): 输入流:把外部输入读入当前程序所在内. 输出流:把当前程序所在内存的 ...

  9. discuz用户登录不响应,提示nginx gateway timeout解决方法

    在使用nginx+php-cgi搭建discuz论坛过程中,出现论坛登录不响应,一直提示nginx gateway timeout504网关超时,单单采用php方式登录无问题.但因需要使用nginx把 ...

  10. windows环境下使用virtualenv对python进行多版本隔离

    最近在用python做一个文本的情感分析的项目,用到tensorflow,需要用python3的版本,之前因为<机器学习实战>那本书的缘故,用的是python2.7.所以目前的情况是要两个 ...