POJ 3159 Candies spfa

点击打开链接

题意:就是裸的的差分约束。

题解:因为差分方向固定,所以只有正权,可以用dijkstra,但是要用队列优化。我用的是spfa和栈。

这里学习了存边迭代的spfa。

add函数里面的tot是边的编号。

head[i]表示当前最新的从i发出的边的编号(对于起始点就是-1),每加入一条边这条边的起点的head也更新。

edge的next指向加入这条边时的起点的head。

遍历的时候,从head[u]号边开始,到遍历到-1为止。

#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
#define N 30010
#define M 150010
#define INF 0x3f3f3f3f

int head[N];
struct edge{
   int u,v,w,next;
}e[M];
int d[N];
int n,tot;
bool vis[N];

void add(int u ,int v ,int w){
   e[tot].u = u; e[tot].v = v; e[tot].w = w;
   e[tot].next = head[u]; head[u] = tot++;
}

void spfa(int s, int t){
	int i;
	stack <int > sta;
	sta.push(s);
	memset(d,0x3f,sizeof(d));
	memset(vis,false,sizeof(vis));
	d[s]=0;
	vis[s]=true;
	while(!sta.empty()){
		int u,v,w;
		u=sta.top();
		sta.pop();
		vis[u]=false;
		for(i=head[u];i!=-1;i=e[i].next){
			u=e[i].u;
		        v=e[i].v;
		        w=e[i].w;
		        if(d[u]+w<d[v]){
				d[v]=d[u]+w;
				if(!vis[v]){
					sta.push(v);
					vis[v]=1;
				}
		        }
		}
	}
	printf("%d\n",d[t]);
}

int main()
{
   int n,m;
   int i;
   scanf("%d%d",&n,&m);
   tot=0;
   memset(head,-1,sizeof(head));
   for(i=1;i<=m;i++){
	int u,v,w;
	scanf("%d%d%d",&u,&v,&w);
	add(u,v,w);
   }
   spfa(1,n);
   return 0;
}

猜你喜欢

转载自blog.csdn.net/nwpu2017300135/article/details/81052953