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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章