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. 简单RPC框架-基于Consul的服务注册与发现

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  2. iOS 比较版本号大小的方法

    比较iOS版本号大小 eg:3.2.0和3.1.0 或者 3.2.0和3.2比较 返回bool值变量YES or NO -(BOOL)compareVesionWithServerVersion:(N ...

  3. SparkMLlib回归算法之决策树

    SparkMLlib回归算法之决策树 (一),决策树概念 1,决策树算法(ID3,C4.5 ,CART)之间的比较: 1,ID3算法在选择根节点和各内部节点中的分支属性时,采用信息增益作为评价标准.信 ...

  4. asp.net core利用DI实现自定义用户系统,脱离ControllerBase.User

    前言 很多时候其实我们并不需要asp.net core自带的那么复杂的用户系统,基于角色,各种概念,还得用EF Core,而且在web应用中都是把信息存储到cookie中进行通讯(我不喜欢放cooki ...

  5. SmartCoder每日站立会议06

    站立会议内容 讨论了小程序的具体实现方式,主要会加入地图这一元素,使程序看起来更加的方便直观,同时也会使人感到新颖.在对各个点的评论对话功能也在考虑中. 1. 站立会议照片: 2.任务展板 3.燃尽图

  6. 可视化Git版本管理工具SourceTree的使用

    最近去了新公司,发现公司使用的团队版本管理工具是SourceTree,本人一直是SVN的热衷粉,很少使用git,所以从头学习git及可视化客户端SourceTree的使用,本贴只针对新手,大牛可以无视 ...

  7. [netty源码分析]3 eventLoop 实现类SingleThreadEventLoop职责与实现

    eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...

  8. linux升级openssh7.4sp1

    1.准备相关的包 openssh下载地址:http://mirror.internode.on.net/pub/OpenBSD/OpenSSH/portable/ openssl相关包下载:http: ...

  9. Spring+SpringMVC+MyBatis深入学习及搭建(七)——MyBatis延迟加载

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6953005.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(六)——My ...

  10. Java-集合框架总结

    集合框架: Java中的集合框架大类可分为Collection和Map:两者的区别: 1.Collection是单列集合:Map是双列集合 2.Collection中只有Set系列要求元素唯一:Map ...