題意:
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;
}