poj 3159 Candies 最短路 dijkstra堆优化

题意:
n个人,m个信息,每行的信息是3个数字,A,B,C,表示B比A多出来的糖果不超过C个,问你,n号人最多比1号人多几个糖果

Input:
输入包含单个测试用例。测试用例以两个整数n和m开头,分别不超过30000和150000。n是班上的孩子数,孩子数从1到n。snoopy和flymouse始终是1和n。然后按照m行,每一行依次包含三个整数a、b和c,这意味着孩子a相信孩子b永远不会比他得到更多的c糖果。
翻译成人话就是:n个点,m条边。以及m条单向边的信息。

Output:
只输出一行所需的最大差异。差分是有限的。(即输出dis[i])

思路 :
参考大佬:①https://blog.csdn.net/qq_21057881/article/details/50574215
②https://blog.csdn.net/h1021456873/article/details/66472713

  • 对应最短路模型,在松弛完最短路后则变为 d[v] <= d[u] + w ,转化为 d[v] - d[u] <= w,这个和上面的 B - A <= C 是相同的模式 , 因此建图的时候A和B连一条有向边 , 边权为C,以1为起点,n为终点跑一遍最短路即可
  • 班上有n个同学,现在有一些糖要分给他们,设第i个同学得到的糖为p[i],分糖必须满足条件:第i个同学要求第j个同学的糖不能超过自己k个,即p[j] - p[i] <= k,k >= 0。要求在满足这些条件的情况下,求出p[n] - p[1]的最大值。
  • 由p[j] - p[i] <= k可得p[j] <= p[i] + k
  • 在单源最短路径的算法中有一步是“若mindis[j] > mindis[i] + dis[i][j],则mindis[j] = mindis[i] + dis[i][j],这样就满足mindis[j] <= mindis[i] + dis[i][j]”。因此本题可以使用单源最短路径的算法来解决,对于“第i个同学要求第j个同学的糖不能超过自己k个,即p[j] - p[i] <= k,k >= 0”这个条件,建立一条边(i->j)=k,由于不含负权路径,因此建立完所有边之后以第1个同学为起点,采用Dijkstra+Heap求最短路径即可。除了Dijkstra也可以利用Spfa+Stack算法求解,但由于数据原因必须用Stack,如果用Queue则会超时。

自己交了第一发WA了,原因是开EDGE的数组时候这么写的

//const int maxn = 30000+50;
EDGE edge[3*maxn];

改成下面代码后AC

EDGE edge[150000+10];

md傻了,应该是5*maxn才对啊!!!

#pragma warning(disable:4996)
#include<iostream>
#include<string>
#include<cmath>
#include<ctype.h>
#include<memory.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<iomanip>
#include<set>
#include<list>
#include<vector>
#include<stack>
#include<queue>
#define ll long long int
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 30000+50;

struct EDGE
{
	int v, w;
	int next;
};
EDGE edge[150000+10];//3*maxn为什么不行

struct node
{
	int to, dis;
	node(int u, int d)
		:to(u), dis(d) {}
	bool operator <(const node& p)const
	{
		return dis > p.dis;
	}
};

int n, m;
int cnt = 0;
int head[maxn];
int dis[maxn];
int vis[maxn];

void ini()
{
	cnt = 0;
	for (int i = 0; i <= n; i++)
	{
		head[i] = -1;
		vis[i] = 0;
		dis[i] = INF;
	}
}

void addedge(int u, int v, int w)
{
	edge[cnt].v = v;
	edge[cnt].w = w;
	edge[cnt].next = head[u];
	head[u] = cnt;;
	cnt++;
}

void dijkstra(int s)
{
	priority_queue<node> q;
	q.push(node(s, 0));

	dis[s] = 0;

	while (!q.empty())
	{
		node now = q.top(); q.pop();

		int u = now.to;
		if (!vis[u])
		{
			vis[u] = 1;
			for (int i = head[u]; i != -1; i = edge[i].next)
			{
				int v = edge[i].v;
				int w = edge[i].w;
				if (!vis[v] && dis[v] > dis[u] + w)
				{
					dis[v] = dis[u] + w;
					q.push(node(v, dis[v]));
				}
			}
		}
	}
}

int main()
{
	cin >> n >> m;
	ini();
	for (int i = 0; i < m; i++)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, w);
	}
	dijkstra(1);
	cout << dis[n] << endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章