小孩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 ;
}