POJ3249Test for Job(拓扑排序+DP)

题意就是给一个有向无环图,每个点都有一个权值,求从入度为0的点到出度为0点路径上经过点(包括起点终点)的权值和的最大值。

分析:

注意3点

1.本题有多组数据

2.可能有点的权值是负数,也就是结果可能为负,初值要设为负无穷。

3.入度或出度为0的点不止一个。

注意以上几点本题就很简单了,用到DP dis[i]:=max(dis[j],dis[i]+w[j])在拓扑排序过程同时进行即可。

考前练练拓扑排序和指针。

代码:

program test;
type
  point=^node;
  node=record
       data:longint;
       next:point;
    end;
var
  a:array[0..100000]of point;
  w,u,v,dis,f:array[0..100000]of int64;
  n,i,m,t,x,y,num:longint;
  ans:int64;
  p:point;
function max(x,y:int64):int64;
begin
  if x>y then max:=x else max:=y;
end;
begin
  while  not eof do
  begin
  readln(n,m);
  for i:=1 to n do
    readln(w[i]);
  for i:=1 to n do
    a[i]:=nil;
  t:=0;  ans:=-maxlongint; num:=0;
  fillchar(u,sizeof(u),0);  fillchar(v,sizeof(v),0);
  for i:=1 to m do
   begin
     readln(x,y);
     new(p); p^.data:=y; p^.next:=a[x]; a[x]:=p;
     u[y]:=u[y]+1; v[x]:=v[x]+1;
   end;
  for i:=1 to n do dis[i]:=-maxlongint;
  for i:=1 to n do if u[i]=0 then begin inc(t); f[t]:=i; dis[i]:=w[i]; end;
  repeat
    x:=f[t]; dec(t); inc(num);
    new(p); p:=a[x];
    while p<>nil do
     begin
       y:=p^.data; dis[y]:=max(dis[y],dis[x]+w[y]);
       dec(u[y]);
       if u[y]=0 then
        begin
          inc(t); f[t]:=y;
        end;
       p:=p^.next;
     end;
  until num=n;
  for i:=1 to n do
   if v[i]=0 then ans:=max(ans,dis[i]);
  writeln(ans);
  end;
end.

时间: 2024-11-08 12:07:06

POJ3249Test for Job(拓扑排序+DP)的相关文章

POJ 3249 Test for Job 拓扑排序+DP

http://poj.org/problem?id=3249 题意: 给一个有向无环图DAG(不一定联通),每个点有权值,入度为0的点为起点,出度为0的点为终点,选择一个起点走到一个终点,使得路上的权和最大. 分析: dp[to] = max(dp[from]) + value[to],然后先拓扑排序保证状态正确转移即可,终点做标记,如果是终点则尝试更新答案. update:因为点权可以为负,所以程序里用dp[i] == -1表示未访问过该点是有问题的,不过没有遇上会卡掉这种情况的数据=.= 1

POJ 3249 拓扑排序+DP

貌似是道水题.TLE了几次.把所有的输入输出改成scanf 和 printf ,有吧队列改成了数组模拟.然后就AC 了.2333333.... Description: MR.DOG 在找工作的过程中呢.遇见了这样一个问题.有n个城市,m条小道.然后要从入度为0的点出发,出度为0的点结束,中途经过的城市呢,都是要付费的.负数表示花费.正数表示收益.然后让你求收益最大或者说花费最少的总值. 貌似.BFS和DFS都会超时.不妨一试.附代码: #include<stdio.h>#include<

[Luogu P3953] 逛公园 (最短路+拓扑排序+DP)

题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易可以想到一个做法,就是魔改迪杰斯特拉做法: 如果一个点可以更新到达其他点的距离,那个点的方案数就是这个点的方案数:如果一个点所更新出来的距离和之前的相等,那个点的方案数加等当前点的方案数. 用式子可以表现为: f[j]=f[i] (dis[j]>dis[i]+x)   f[j]+=f[i] (dis

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

Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10137   Accepted: 2348 Description Mr.Dog was fired by his company. In order to support his family, he must find a new job as soon as possible. Nowadays, It's hard to have a jo

NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)

神tm比赛时多清个零就有60了T T 首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP.设f[i][j]表示比最短路多走i的长度,到j的方案数. 我们发现如果在最短路上的和零边会有后向性,怎么办呢?拓扑排序. 把最短路上的点和零边的点拉出来跑拓扑排序,如果有零环的话必定度数不为0,而且要注意零环必须在<=最短路+k的路径上才输出-1,这个就用刚刚跑出来的1起点到n起点的最短路来判断就好了. 然后先按拓扑序DP出i相同的,然后再DP不在最短路上或者零边的. #include<iost

【tarjan 拓扑排序 dp】bzoj1093: [ZJOI2007]最大半连通子图

思维难度不大,关键考代码实现能力.一些细节还是很妙的. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,则称G'是G的一个导出子图.若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图.若G'是G所有半连通子图中包含节点数最多的,则称G'是G的最大半连通子图.给

[HAOI2012] 道路 - 最短路图,拓扑排序,dp

给定一个无向图,一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路.\(n\leq 1500,m\leq 5000,w\leq 10000\) Solution 枚举每个点作为起点,跑出最短路径图,对其拓扑排序后,DP 统计出每个点发出和从起点到达该点的最短路的总数,然后扫一遍所有边统计答案即可. 注意可能有重边 #include <bit

Codefroces 919D Substring(拓扑排序+DP)

题目链接:http://codeforces.com/problemset/problem/919/D 题目大意:给你一张有向图,给你每个顶点上的字母和一些边,让你找出一条路径,路径上的相同字母数最多,输出最大相同字母数,若可以无穷多则输出-1(成环). 解题思路:因为是有向图,所以可以直接利用拓扑排序,拓扑排序过程中用f[i][j]记录到第i个点为止的路径,出现字母j的最大出现次数即可. 代码: 1 #include<iostream> 2 #include<cstdio> 3

[ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓扑序DP,要去掉所有的重边. Code #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=100008; struct sj{int to,next;}a[maxn*10]; ll mo