小孩A认为小孩B比自己多出的最多不会超过c个糖果,也就是 B - A <= c,正好符合差分约束方程,就是A到B的边权w(A, B) = c;用 SPFA + 栈 能过。
这里有两种加边方式:
第一种:我以前用的,用这个超时了,因为每次加边都是将边夹在邻接表的最后面,需要一个查找时间,这题数据量大,自然就超时了。
代码
void add(int a, int b, int c){
int tmp;
edge[edNum].e = b;
edge[edNum].v = c;
next[edNum] = -1;
tmp = root[a];
if (tmp == -1){
root[a] = edNum;
}else{
while (next[tmp] != -1){
tmp = next[tmp];
}
next[tmp] = edNum;
}
edNum++;
}
第二种:这种我刚学到的,比较好,每次把边加在最前面,突然想起sjr有一道题的加边方法和这个一样,那时怎么就看不懂,大概是不懂邻接表的缘故吧。
void add(int a, int b, int c){
edge[edNum].e = b;
edge[edNum].v = c;
next[edNum] = root[a];
root[a] = edNum++;
}
这题还得用栈实现,用队列超时,我开始用队列,一直TLE,我这里写了两个,Spfa()是用队列实现的,Spfa1是用栈实现的。
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define INF 0xfffffff
#define MM 150004
#define NN 30004
int edNum, N;
struct node{
int e, v;
}edge[MM];
int next[MM];
int dis[NN];
int root[NN];
int que[NN];
int mark[NN];
int stack[NN];
void add(int a, int b, int c){
int tmp;
edge[edNum].e = b;
edge[edNum].v = c;
next[edNum] = root[a];
root[a] = edNum++;
}
void Spfa()
{
int i, quNum, tmp, nxt, cur;
for (i = 1; i <= N; i++){
dis[i] = INF;
}
dis[1] = 0;
quNum = 0;
for (i = 1; i <= N; i++){
if (root[i] != -1){
que[quNum++] = i;
mark[i] = 1;
}
}
for (i = 0; i != quNum; i = (i + 1) % (N + 1)){
cur = que[i];
tmp = root[cur];
while (tmp != -1){
nxt = edge[tmp].e;
if (dis[nxt] > dis[cur] + edge[tmp].v){
dis[nxt] = dis[cur] + edge[tmp].v;
if (!mark[nxt]){
mark[nxt] = 1;
que[quNum] = nxt;
quNum = (quNum + 1) % (N + 1);
}
}
tmp = next[tmp];
}
mark[cur] = 0;
}
}
void Spfa1()
{
int i, top, tmp, nxt, cur;
for (i = 1; i <= N; i++){
dis[i] = INF;
}
dis[1] = 0;
top = 0;
for (i = 1; i <= N; i++){
if (root[i] != -1){
stack[++top] = i;
mark[i] = 1;
}
}
while (top){
cur = stack[top--];
tmp = root[cur];
mark[cur] = 0;
while (tmp != -1){
nxt = edge[tmp].e;
if (dis[nxt] > dis[cur] + edge[tmp].v){
dis[nxt] = dis[cur] + edge[tmp].v;
if (!mark[nxt]){
mark[nxt] = 1;
stack[++top] = nxt;
}
}
tmp = next[tmp];
}
}
}
int main()
{
int M, a, b, c, i;
scanf("%d%d", &N, &M);
edNum = 0;
for (i = 0; i <= N; i++){
root[i] = -1;
mark[i] = 0;
}
while (M--){
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
Spfa1();
printf("%d\n", dis[N]);
//system("pause");
return 0;
}