POJ-1511 Invitation Cards【最短路】

news/2024/7/10 5:12:43 标签: 优化, 存储

题目链接:http://poj.org/problem?id=1511


题目大意:

给你一个N个点的图,求1点到其他每个点最短路权值之和sum1,然后再求反向最短路(其他所有点到1点最短距离)之和sum2。输出sum1+sum2


解题思路:

别人说的题意,正好最短路也忘了,就用SPFA写了一下。结果SPFA忘了。。。问了别人,算是懂了。

所谓的SPFA,就是bellman-ford的优化,因为bellman-ford是循环更新每条边n-1次(循环次数固定),但是效率很低,因为不可能每条边都需要更新这么多次吧。所以,出现了SPFA。SPFA的改进之处在于,我加入队列的元素都是已经松弛过,最短距离减小的点,我每次取出对头,更新所以经过这个节点的其他点,如果其他节点的最短距离通过这个队头的点能变小,就松弛。不能就遍历其他点。这样,更新的次数大大减少。

之前我的SPFA是用邻接矩阵实现的,效率之挫就不多说了,因为没有充分利用邻接表的优势,因为邻接矩阵我必须逐个遍历,才能知道两点之间是否存在边,而邻接表存储的就是两点之间相连的边。

这样,SPFA+邻接表的组合就变得更加强大。。。。

总结就是:

最短路题目,最好都使用邻接表+SPFA。这样,差不多就能解决了。(除非特别出数据专门卡SPFA!~~还没遇到~~~~)


代码如下:

#include<iostream>
#include<cstdio>
#include<climits>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;

#define CLR(arr, what) memset(arr, what, sizeof(arr))
const int N = 1000010;
const long long MAX = 10000000000000005; //数据太大。10亿*100W

int Head[N], Next[N], Key[N], Num[N], num;
long long dis[N];
bool visit[N];
int nodenum, edgenum;

struct Edge //结构体存图,方便反向建边
{
	int u, v;
	int weight;
}edge[N];

void add(int u, int v, int cost) //u,v之间加入权值为cost的边
{
	Key[num] = cost;
	Next[num] = Head[u];
	Num[num] = v;
	Head[u] = num++;
}

void init()
{
	num = 0;
	CLR(Head, -1);
	for(int i = 1; i <= nodenum; ++i)
		dis[i] = MAX;
}

long long SPFA(int start)
{
	long long total = 0;
	int temp;
	queue<int> q;
	while(!q.empty())
		q.pop();
	CLR(visit, false);

	dis[start] = 0;
	visit[start] = true;

	q.push(start);
	while(!q.empty())
	{
		temp = q.front();
		q.pop();
		visit[temp] = false;
		for(int i = Head[temp]; i != -1; i = Next[i]) //邻接表实现
		{
			if(dis[Num[i]] > dis[temp] + Key[i])
			{
				dis[Num[i]] = dis[temp] + Key[i];
				if(!visit[Num[i]])
				{
					q.push(Num[i]);
					visit[Num[i]] = true;
				}
			}
		}
	}
	for(int i = 1; i <= nodenum; ++i)
		total += dis[i];
	return total;
}

int main()
{
	int ncase;
	int top;
	long long answer;
	scanf("%d", &ncase);
	while(ncase--)
	{
		top = answer = 0;
		scanf("%d%d", &nodenum, &edgenum);
		init();
		for(int i = 0; i < edgenum; ++i)
		{
			scanf("%d %d %d", &edge[top].u, &edge[top].v, &edge[top].weight);
			add(edge[top].u, edge[top].v, edge[top].weight);
			top++;
		}
		answer += SPFA(1);
		init();
		for(int i = 0; i < top; ++i) //反向图
			add(edge[i].v, edge[i].u, edge[i].weight);
		answer += SPFA(1);
		printf("%lld\n", answer);
	}
	return 0;
}



http://www.niftyadmin.cn/n/1516687.html

相关文章

WINCE6.0下RIL中多路虚拟串口的实现解读

710MUX多路复用驱动程序Mux07_10.dll把一路实际的物理串口虚拟成两路串口。 1。一路虚拟串口是COM7-----用于一般的AT 命令发送2。一路虚拟串口是COM9-----用于ppp connection over CSD / GPRS 看对应的注册表项就可以清楚&#xff0c;下面的内容来自C:/WINCE600/PLATFORM/DE…

在Wince5.0中实现关机功能

wince5.0带的电源管理驱动只实现了“休眠&#xff08;SUSPEND&#xff09;”功能&#xff0c;未实现“关机&#xff08;SHUT_DOWN)”功能。调用函数 SetSystemPowerState()时&#xff0c;无论参数是POWRE_STATE_OFF还是POWRE_STATE_SUSPEND&#xff0c;最终均为 SUSPEND。如果需…

WinCE 5.0下的鼠标键盘驱动分析

WinCE 5.0下鼠标键盘驱动分析 WinCE 5.0下鼠标键盘驱动分析 本文通过对WinCE 5.0下的鼠标键盘驱动分析&#xff0c;对WinCE驱动程序设计进行了分析。欢迎大家对不对的地方指出。 硬件 写一个驱动程序的第一件事就是读硬件的规范文档。所以首先必须了解硬件才能写好驱动…

NYOJ-303 序号互换【模拟】

题目链接&#xff1a;http://acm.nyist.net/JudgeOnline/problem.php?pid303 解题思路&#xff1a; 省赛的水题。写了一下&#xff0c;第一次把题意理解错了&#xff0c;然后第二次写&#xff0c;发现数字转字母不会。。YY了才知道最后一个是Z时&#xff0c;总是2626的0次方&…

从软件工程师到IT猎头续:告诉你如何写简历

做IT猎头也有一段光景&#xff0c;看过无数简历&#xff0c;可谓是仪态万千&#xff0c;各领风骚&#xff0c;有的看起来头大&#xff0c;有的改起来吐血&#xff0c;有的直接使人崩溃....  有些是那种在简历中写的一大段描述性的文字&#xff0c; 让HR或者猎头拿到这样的简历…

WINCE键盘驱动流程不完全分析

键盘驱动有点繁杂&#xff0c;可以配合以下资料查阅: 1. Platform Build自带的帮助文件. 2. 阅读源代码: 2.1 C:/WINCE420/Public/common/oak/drivers/keybd 2.2 C:/WINCE420/Platform/smdk2410/drivers/keybd 3. 网上的一些相关资料 初步查阅后可以知道&am…

NYOJ-183 赚钱啦【最短路】

题目链接&#xff1a;http://acm.nyist.net/JudgeOnline/problem.php?pid183 解题思路&#xff1a; 最短路裸题。 最长路判断正环 学会的东西是如何用SPFA判断负环&#xff0c;可以用一个数组维护每个节点入队的次数&#xff0c;超过n次就肯定有负环出现。 代码如下&#x…

Hdu-1215 七夕节【算术基本定理应用】

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1215 解题思路&#xff1a; 这道题要求的就是一个整数的因子之和。 但是这道题在杭电数据比较弱&#xff0c;各种方法都能过。暴力都能过&#xff0c;但是在我们OJ&#xff0c;只能使用优化的代码。因为数据…