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. MySql学习笔记(一) —— 关键字的使用

    1.distinct关键字 作用:检索出有不同值的列,比如一个商品表中存在供应商vend_id,一个供应商会对应很多商品,我们要查找有多少供应商,就可以用到该关键字去重. select distinc ...

  2. Kotlin初探

    前几天看到新闻,Google将Kotlin语言作为Android应用开发的一级语言, 与Java并驾齐驱, 这则消息在开发界一下就炸开了锅( 好像平息的很快...)! 连Google的亲儿子go语言也 ...

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

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

  4. 搞定python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  5. net.sf.json.JSONException: java.lang.reflect.InvocationTargetException Caused by: java.lang.IllegalArgumentException at java.sql.Date.getHours(Unknown Source)

    数据库字段类型为Date,转成JSON格式会有问题,解决方案如下: json-lib有一个配置类JsonConfig通过JsonConfig可以注册一个字段处理器实现JsonValueProcesso ...

  6. shiro不重启动态加载权限

    最近一朋友让我帮他做一个后台权限管理的项目.我就在我原来的项目加加改改但是还是不理想,查了不少资料也走了不了弯路...... shiro基本的配置我就不多说了这个很简单自己查查资料就完成----下面是 ...

  7. 跟着刚哥深入学maven

    前言:目前所有的项目都在使用maven,可是一直没有时间去整理学习,这两天正好有时间,好好的整理一下. 一.为什么使用Maven这样的构建工具[why] ① 一个项目就是一个工程 如果项目非常庞大,就 ...

  8. C. Friends

    C. Friends 题意 对于任一点,求到此点距离不超过6的节点数. 分析 第一次dfs,形成一个以 1 为根的有向树,设 down[i][j] 为以i为根节点,距离 i 点距离不超过 j 的节点数 ...

  9. 数据库MySQL安装和校验

    1.安装MySQL 双击已经下载的安装包: Typical:典型安装,第一次安装建议选择该类安装 Custom:自定义安装,在对数据库熟悉后,知道自己需要哪些组件时,可以选择该类安装(这里选择的是自定 ...

  10. 一天搞定CSS---终篇CSS总结

    虽然说是一天搞定CSS,实际上也没有那么简单.只能说让你快速了解常见的CSS知识,解决基本的页面样式布局和设置. 每个独立的CSS知识点都比较简单,但是它们的应用非常灵活,特别是在综合应用中. 粗略说 ...