堆优化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. memcache的内存管理机制

    Memcache使用了Slab Allocator的内存分配机制:按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题Memcache的存储涉及到slab,page,chunk三 ...

  2. FZU1465

    题目链接:传送门 题目大意:给你n个整数(可正可负),求有多少个连续的子序列的和==m(时限1S) 题目思路:前缀和+手写hash(map效率太慢,会超时) 具体做法是用一个数组sum,数组的第i位保 ...

  3. 170223、Tomcat部署时war和war exploded区别以及平时踩得坑

    war和war exploded的区别 在使用IDEA开发项目的时候,部署Tomcat的时候通常会出现下边的情况: 是选择war还是war exploded 这里首先看一下他们两个的区别: war模式 ...

  4. windosw启动redis

    1.cmd控制台 cd C:\Program Files\Redis 2.redis-server.exe redis.windows.conf 3. ok!!

  5. 【IDEA】重装基本设置+插件安装

    基本配置:2.1 显示:2.1.1.选中展示Toolbar2.1.2.显示内存占用:2.1.3.显示行号和方法线:2.1.4.代码软分行:2.2.修改快捷键:2.2.1 修改Ctrl + D 快捷键: ...

  6. sqlserver----记录转载(行转列)、列转行、pivot、unpivot

    CREATE TABLE [StudentScores] ( ), --学生姓名 ), --科目 [Score] FLOAT, --成绩 ) 如果我想知道每位学生的每科成绩,而且每个学生的全部成绩排成 ...

  7. to_base64 --- from_base64

    UPDATE traceroleid_copy SET Pwd=to_base64(Pwd) SELECT from_base64(Pwd) FROM traceroleid_copy

  8. spring 攻略

    1.5 指定Bean引用 为了Bean之间相互访问,在Bean配置文件中通过<ref>元素为Bean属性或构造程序参数指定Bean引用. <property name="p ...

  9. 将Android studio的工程导入到eclipse中

    自从Android Studio(后面称AS)推出后,越来越多的项目都使用AS开发. AS往eclipse迁移的方法: 其实很简单,代码都是一样的,从AS工程中找到与Eclipse工程对应的文件,放到 ...

  10. Spring 框架的 applicationContext.xml 配置文件

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...