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