显然是一道最短路径的题目,但是

1 ≤ n ≤ 100000, 0 ≤ m ≤ 1000000能轻松打爆dij+heap

怎么办?

挖掘题意,这是一个DAG图(有向无环图)

所以对于此类问题,我们有特殊的作法

对于DAG,拓扑序列在前的点的最短路一定会被先更新(值得思考)

所以我们只用对DAG做一次拓扑,然后依次更新最短路即可;(其实很像dp)

多个入度为0的点不影响结果;

再回到这题,由于给出的是点的权值

可以考虑拆点,将点i拆成点i1,i2,i1,i2之间连一条指向i2的有向边,权值为原先点的权值

原先所有入边连向i1,出边连i2,权值都是0,这样就搞定了

拆点的做法在后面的网络流中会经常用到(当然这题也可以不拆)

 type link=^node;
     node=record
       po,len:longint;
       next:link;
     end; var w:array[..] of link;
    v:array[..] of boolean;
    c,r,q,d:array[..] of longint;
    n,m,ans,i,t,f,s,x,y:longint;
    p,g:link;
function max(a,b:longint):longint;
  begin
    if a>b then exit(a) else exit(b);
  end; procedure add(x,y,z:longint);  //邻接表
  var p:link;
  begin
    new(p);
    p^.po:=y;
    p^.len:=z;
    p^.next:=w[x];
    w[x]:=p;
  end; begin
  while not eoln do
  begin
    readln(n,m);
    for i:= to *n do
      w[i]:=nil;
    fillchar(r,sizeof(r),);
    fillchar(c,sizeof(c),);
    for i:= to n do  //拆点
    begin
      readln(x);
      add(i+n,i,x);
      inc(r[i]);
      inc(c[i+n]);
    end;
    for i:= to m do  //建边
    begin
      readln(x,y);
      add(x,y+n,);
      inc(r[y+n]);
      inc(c[x]);
    end;
    s:=;
    fillchar(v,sizeof(v),false);
    fillchar(q,sizeof(q),);
    for i:= to *n do   //先找入度为0的点
      if r[i]= then
      begin
        inc(s);
        v[i]:=true;
        q[s]:=i;
      end;
    f:=;
    while s<*n do      //生成拓扑序列
    begin
      inc(f);
      p:=w[q[f]];
      while p<>nil do
      begin
        dec(r[p^.po]);
        if r[p^.po]= then
        begin
          inc(s);
          q[s]:=p^.po;
        end;
        p:=p^.next;
      end;
    end;
    for i:= to *n do     //d[i]表示从某个入度为0的点到达当前点的最大距离
      if v[i] then d[i]:= else d[i]:=-;
    ans:=-;
    for i:= to *n do
    begin
      f:=q[i];
      p:=w[f];
      g:=nil;
      while p<>nil do   //按照拓扑序列依次更新所有到达的点
      begin
        t:=p^.po;
        d[p^.po]:=max(d[p^.po],d[f]+p^.len);
        g:=p;
        p:=p^.next;
        dispose(g);   //注意这题多测加上巨大的n,m很有可能把链表挤爆,所以及时释放掉空间
      end;
    end;
    for i:= to *n do
      if c[i]= then ans:=max(d[i],ans);
    writeln(ans);
  end;
end.

拓扑序列复杂度O(m),最短路O(m)

所以总的复杂度O(m)

poj3249的更多相关文章

  1. POJ3249:Test for Job

    传送门 很简单的一道题,被卡了几次,死于答案非法统计. 题意是求图里的一条最长的路径满足起点的入度和终点的出度都是0,而且图是DAG. 既然是DAG求最长路,DP即可.搞出拓扑序,逆序DP,然后统计所 ...

  2. poj3249 Test for Job ——拓扑+DP

    link:http://poj.org/problem?id=3249 在拓扑排序的过程中进行状态转移,dp[i]表示从起点到 i 这个点所得到的的最大值.比如从u点到v点,dp[v]=max(dp[ ...

  3. poj3249 拓扑排序+DP

    题意:给出一个有向无环图,每个顶点都有一个权值.求一条从入度为0的顶点到出度为0的顶点的一条路径,路径上所有顶点权值和最大. 思路:因为是无环图,则对于每个点经过的路径求其最大权值有,dp[i]=ma ...

  4. POJ3249(DAG上的dfs)

    Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10567   Accepted: 2482 Des ...

  5. poj3249【拓扑排序】

    //题意:   给出一个有向无环图,每个顶点都有一个权值. //         求一条从入度为0的顶点到出度为0的顶点的一条路径, //         路径上所有顶点权值和最大. //我觉得只要明 ...

  6. POJ3249 Test for Job(拓扑排序+dp)

    Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10137   Accepted: 2348 Des ...

  7. poj3249 Test for job 【图的DAG dp】

    #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> ...

  8. poj3249 拓扑找最长路

    Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 11230   Accepted: 2651 Des ...

  9. Test for Job(poj3249)

    Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10209   Accepted: 2372 Des ...

随机推荐

  1. sublime 修改Xdebug插件快捷键

    最近在用Xdebug插件 感觉挺好用 但是快捷键不太舒服,特别是调试下一步的时候,比较麻烦,按键较多: 所以想DIY下 但是preferences->package setting ->X ...

  2. mysql中limit的用法实例解析

    mysql中limit的用法解析. 在mysql中,select * from table limit m,n.其中m是指记录开始的index,从0开始,n是指从第m条开始,取n条. 例如: mysq ...

  3. PHP去掉转义后字符串中的反斜杠\函数stripslashes

    addslashes函数主要是在字符串中添加反斜杠对特殊字符进行转义,stripslashes则是去掉转义后字符串中的反斜杠\,比如当你提交一段 json数据到PHP端的时候可能会遇到json字符串中 ...

  4. delphi中的临界区

    var fLock:TRTLCriticalSection; //定义临界区域 // 初始化 InitializeCriticalSection(fLock); //进入临界区 EnterCritic ...

  5. 怎样在自己的网站上做自动生成当前url的二维码

    $todoString="www.maomii.com"; generateQRfromGoogle($todoString); /** * google api 最多4296个字 ...

  6. Oracle访问数据的存取方法

    1) 全表扫描(Full Table Scans, FTS) 为实现全表扫描,Oracle读取表中所有的行,并检查每一行是否满足语句的WHERE限制条件.Oracle顺序地读取分配给表的每个数据块,直 ...

  7. 汽车之家, 比亚迪等成为开源数据库SSDB的用户

    开源的 NoSQL 数据库 SSDB 已经一岁多了! 在这一年中, SSDB 不断被应用在众多业界知名互联网企业, 创业团队的产品中. 最近, 比亚迪汽车也成为 SSDB 的用户, 其将 SSDB 作 ...

  8. easy ui easyui-linkbutton 禁用、启用

    <a id="btn_update_Shop" name="btn_update_Shop" class="easyui-linkbutton& ...

  9. servlet的生命周期与工作原理、使用!

    概念: Servlet是一个java程序运行在服务器上,处理客户端请求并做粗响应的程序!Servlet是和平台无关的服务器组件,它运行在Servlet容器中,Servlet容器 负责servlet和客 ...

  10. 实时数据处理环境搭建flume+kafka+storm:4.storm安装配置

    1.解压 apache-storm-0.9.3.tar.gz   2.修改配置文件 conf/storm.yaml --zk地址  storm.zookeeper.servers:  - " ...