Candies

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

 

posted on 2010-07-21 20:24  ylfdrib  阅读(400)  评论(0编辑  收藏  举报