堆优化Dij VS Spfa 堆优化Dij小胜一筹。

题目名字:Father Christmas flymouse (POJ 3160)

这题可以说是图论做的比较畅快的一题,比较综合,很想说一说。

首先题目大概意思就是走图拿点权,问说最大能拿到多少。一开始看到这题第一反应是挺好做的吧,因为每个点可以走多次,但是点权只能拿一次(可以路过不拿),这个个人觉得难度系数一下就降低了(如果每个点只能过一次就真的不会了。。。)于是乎,我们可以这样想,想要拿走的最大,肯定不想拿负点权,又因为每个点可以只走不拿,那负点权直接输入赋0就可以了,反正肯定只是路过不去拿,那干脆赋0,这样写的时候都拿也等于没有拿,点权问题解决了,接下来可以说就可以愉快的跑最短路了,其实是最长路,但是道理是一样的,能跑最短路肯定也能最长路,只是比较的符号问题。但是跑最短路之前,可以不可以想一想有没有神奇的优化,答案是有的,因为有向图,所以我们可以缩点(考虑tarjan,笔者也只会这个。。而且笔者感觉必须缩点,因为一旦有环(因为负值全部被赋0),那最长路最跑越长就出不来了),缩点染色完重新建图,合并点权(一定要小心,之前合并错了一次,合并一错肯定就是WA不用说)就是愉快的最短路了。

下面符个代码,第一次写题目博客有点激动,很不熟练,望看官指点,不胜感谢。

(个人习惯染色从1开始,这也是学习tarjan博客博客的一个写法,所以设了一个0为总原点,能到染色完的各个强联通分量)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define ms(a,b) memset((a),(b),sizeof(a))
#define fi first
#define se second
#define mp make_pair
using namespace std; typedef pair<int,int> pii;
const int N = 3e4 + 16;
vector<int> sono[N], sonn[N]; int n, m;
int sum, top, depth;
bool vis[N], _vis[N];
int low[N], dnf[N], sta[N], col[N];
int valn[N], valo[N];
int dis[N]; void tarjan( int u )
{
low[u] = dnf[u] = ++depth;
sta[++top] = u;
vis[u] = 1; for ( int i = 0; i < sono[u].size(); i ++ )
{
int v = sono[u][i];
if ( !dnf[v] )
{
tarjan(v);
low[u] = min( low[u], low[v] );
}
else
{
if ( vis[v] )
{
low[u] = min( low[u], low[v] );
}
}
} if ( low[u] == dnf[u] )
{
vis[u] = 0;
col[u] = ++sum;
while ( sta[top] != u )
{
vis[ sta[top] ] = 0;
col[ sta[top--] ] = sum;
}
top --;
}
} void Build()
{
for ( int i = 1; i <= sum; i ++ )
sonn[0].push_back(i); for ( int i = 1; i <= n; i ++ )
valn[ col[i] ] += valo[ i ]; for ( int i = 1; i <= n; i ++ )
{
for ( int j = 0; j < sono[i].size(); j ++ )
{
if ( col[i] != col[ sono[i][j] ] )
sonn[ col[i] ].push_back( col[ sono[i][j] ] );
}
}
} int dij( int s )
{
priority_queue< pii > q;
ms(dis,0);
dis[s] = 0;
q.push( mp(0,s) ); while ( !q.empty() )
{
pii now = q.top();
q.pop(); if ( now.fi < dis[now.se] ) continue; for ( int i = 0; i < sonn[now.se].size(); i ++ )
{
int v = sonn[now.se][i];
if ( dis[v] < now.fi + valn[v] )
{
dis[v] = now.fi + valn[v];
q.push( mp(dis[v],v) );
}
}
} int ans = 0;
for ( int i = 1; i <= sum; i ++ )
{
ans = max( ans, dis[i] );
}
return ans;
} int spfa( int s )
{
queue<int> q;
ms(dis,0);
dis[s] = 0;
_vis[s] = 1;
q.push(s); while ( !q.empty() )
{
int now = q.front();
q.pop();
_vis[now] = 0; for ( int i = 0; i < sonn[now].size(); i ++ )
{
int v = sonn[now][i];
if ( dis[v] < dis[now] + valn[v] )
{
dis[v] = dis[now] + valn[v];
if ( !_vis[v] )
{
_vis[v] = 1;
q.push(v);
}
}
}
} int ans = 0;
for ( int i = 1; i <= sum; i ++ )
{
ans = max( ans, dis[i] );
}
return ans;
} void init( int n )
{
sum = top = depth = 0;
for ( int i = 0; i <= n+1; i ++ )
{
sonn[i].clear();
sono[i].clear();
low[i] = dnf[i] = 0;
sta[i] = vis[i] = col[i] = 0;
dis[i] = 0;
valn[i] = valo[i] = 0;
}
} int main()
{
while ( ~scanf("%d%d", &n, &m) )
{
init(n); for ( int i = 1; i <= n; i ++ )
{
scanf("%d", &valo[i]);
if ( valo[i] < 0 ) valo[i] = 0;
} for ( int i = 0; i < m; i ++ )
{
int u, v;
scanf("%d%d", &u, &v);
u++;
v++;
sono[u].push_back(v);
} for ( int i = 1; i <= n; i ++ )
if ( !dnf[i] )
tarjan(i); Build();
int ans1 = dij(0);;
// int ans2 = spfa(0);
// printf("%d\n%d\n", ans1, ans2);
printf("%d\n", ans1);
}
return 0;
}

图论_FatherChristmasFlymouse(Tarjan+dijkstra or spfa)的更多相关文章

  1. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  2. 图论-单源最短路-SPFA算法

    有关概念: 最短路问题:若在图中的每一条边都有对应的权值,求从一点到另一点之间权值和最小的路径 SPFA算法的功能是求固定起点到图中其余各点的的最短路(单源最短路径) 约定:图中不存在负权环,用邻接表 ...

  3. 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路

    题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...

  4. hdu1874 畅通project续 最短路 floyd或dijkstra或spfa

    Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择.而某些方案 ...

  5. 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路

    题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...

  6. 图论最短路径算法总结(Bellman-Ford + SPFA + DAGSP + Dijkstra + Floyd-Warshall)

    这里感谢百度文库,百度百科,维基百科,还有算法导论的作者以及他的小伙伴们...... 最短路是现实生活中很常见的一个问题,之前练习了很多BFS的题目,BFS可以暴力解决很多最短路的问题,但是他有一定的 ...

  7. 【uva 658】It's not a Bug, it's a Feature!(图论--Dijkstra或spfa算法+二进制表示+类“隐式图搜索”)

    题意:有N个潜在的bug和m个补丁,每个补丁用长为N的字符串表示.首先输入bug数目以及补丁数目.然后就是对M个补丁的描述,共有M行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,第 ...

  8. 【Tarjan】+【SPFA】APIO2009 Atm

    一.算法介绍 tarjan——求解有向图强连通分量.这个算法在本人的一篇blog中有介绍,这里就不赘述了.贴上介绍tarjan的的blog链接:http://www.cnblogs.com/Maki- ...

  9. Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划

    Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri ...

随机推荐

  1. hdu1066(经典题)

    求N个数阶乘末尾除0后的数值. 主要的难点在于要把这个N个数所含的2和5的队数去掉. 网上方法很多很好. 不多说 Last non-zero Digit in N! Time Limit: 2000/ ...

  2. HDU 1232 畅通工程(Kruskal)

    畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  3. js实现查询关键词,使其高亮

    今天做了一个功能:在页面上查询关键,使其高亮显示,实现代码如下: css: <style type="text/css"> .highlight { backgroun ...

  4. C++ 动态内存 栈堆

    C++ 动态内存_w3cschool https://www.w3cschool.cn/cpp/cpp-dynamic-memory.html

  5. centos6.5关闭防火墙命令

    1.永久性生效,重启后不会复原 开启: chkconfig iptables on 关闭: chkconfig iptables off 2.即时生效,重启后复原 开启: service iptabl ...

  6. 6.Insert Documents-官方文档摘录

    总结 1.插入单文档 db.inventory.insertOne( { item: "canvas", qty: , tags: , w: 35.5, uom: "cm ...

  7. Linux(8)- nginx+uWSGI+virtualenv+supervisor 发布web服务器

    一.理论梳理 WSGI是web服务器的网关接口,它是一个规范,描述了web服务器(下图中的WEB server)如何与web应用程序(下图中的Application)通信,以及web应用程序如何链接在 ...

  8. 2016 安全行业全景图——By 安全牛

    2014年有幸在北京办公室与安全牛的创办人刘朝阳见过一面,从那以后一直关注这安全牛(http://www.aqniu.com/)以及IT经理网(http://www.ctocio.com/).今年初看 ...

  9. 0407-服务注册与发现-Eureka深入理解-元数据、高可用HA

    一.Eureka元数据 参看地址:https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_e ...

  10. alter session set events

    .alter session set events 一.Oracle跟踪文件    Oracle跟踪文件分为三种类型,一种是后台报警日志文件,记录数据库在启动.关闭和运行期间后台进程的活动情况,如表空 ...