图论_FatherChristmasFlymouse(Tarjan+dijkstra or spfa)

堆优化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)的更多相关文章
- 图论算法-Tarjan模板 【缩点;割顶;双连通分量】
		
图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...
 - 图论-单源最短路-SPFA算法
		
有关概念: 最短路问题:若在图中的每一条边都有对应的权值,求从一点到另一点之间权值和最小的路径 SPFA算法的功能是求固定起点到图中其余各点的的最短路(单源最短路径) 约定:图中不存在负权环,用邻接表 ...
 - 【bzoj1179】[Apio2009]Atm  Tarjan缩点+Spfa最长路
		
题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...
 - hdu1874  畅通project续 最短路  floyd或dijkstra或spfa
		
Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择.而某些方案 ...
 - 洛谷  P3627 [APIO2009]抢掠计划  Tarjan缩点+Spfa求最长路
		
题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...
 - 图论最短路径算法总结(Bellman-Ford + SPFA + DAGSP + Dijkstra + Floyd-Warshall)
		
这里感谢百度文库,百度百科,维基百科,还有算法导论的作者以及他的小伙伴们...... 最短路是现实生活中很常见的一个问题,之前练习了很多BFS的题目,BFS可以暴力解决很多最短路的问题,但是他有一定的 ...
 - 【uva 658】It's not a Bug, it's a Feature!(图论--Dijkstra或spfa算法+二进制表示+类“隐式图搜索”)
		
题意:有N个潜在的bug和m个补丁,每个补丁用长为N的字符串表示.首先输入bug数目以及补丁数目.然后就是对M个补丁的描述,共有M行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,第 ...
 - 【Tarjan】+【SPFA】APIO2009 Atm
		
一.算法介绍 tarjan——求解有向图强连通分量.这个算法在本人的一篇blog中有介绍,这里就不赘述了.贴上介绍tarjan的的blog链接:http://www.cnblogs.com/Maki- ...
 - Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划
		
Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri ...
 
随机推荐
- 怎样从Mysql官网下载mysql.tar.gz版本的安装包
			
今天学习在Linux上部署项目,用到了Mysql,因此想要下载适用于Linux的安装版本,在Mysql官网找了半天,终于找到怎样下载了,这里写出来,以后大家找的时候就好找了. 第一步:在百度输入My ...
 - AngularJS 讲解,二 模块
			
AngularJS允许我们使用angular.module()方法来声明模块,这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖列表,也就是可以被注入到模块中的对象列表. angular.mo ...
 - codeforces2015ICL,Finals,Div.1#J Ceizenpok’s formula【扩展lucas】
			
传送门 [题意]: 求C(n,k)%m,n<=108,k<=n,m<=106 [思路]: 扩展lucas定理+中国剩余定理 #include<cstdio> usi ...
 - delphi -----TListView的用法
			
层次关系: TListView: ->Columns: ->Items : -->TListItems: ...
 - 开机启动/etc/rc.local失效无效怎么办?解决方法
			
开机启动/etc/rc.local失效问题的解决方法 第一种情况:当centOS 随机启动文件 /etc/rc.local 失效时请按如下修改1.echo /etc/rc.local >> ...
 - DKLang Translation Editor
			
https://yktoo.com/en/software/dklang-traned Features Translation using a dictionary (so-called Trans ...
 - 解决: ./netapp.bin: error while loading shared libraries: libcaffe.so.1.0.0: cannot open shared object file: No such file or directory 运行时报错(caffe)
			
caffe安装好后lib没有配置到/usr/lib或/usr/local/lib中,需手动配置: export LD_LIBRARY_PATH=/path_to_your_caffe/build/li ...
 - vue事件修饰器
			
事件修饰器 Vue.js 为 v-on 提供了 事件修饰符.通过由点(.)表示的指令后缀来调用修饰符.· .stop .prevent .capture .self <div id=" ...
 - TCP原理
			
1.http://coolshell.cn/articles/11564.html 2.http://coolshell.cn/articles/11609.html 3.一站式学习wireshark ...
 - Python迭代对象、迭代器、生成器
			
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...