PKU 1511 SPFA ( 静态邻接表)

/*

	题意:给出一个图,求源点到其他各个点之和  加上   其他各个点到源点之和的最小值



	思路:SPFA, 建两个表,顺序不说,

	      逆序的情况:在初始化的时候在反向保存另一相同表

		              即:    1 ---> 2   13

					  反向后:2 ---> 1   13

					  要求各点到源点的距离和,即求源点到各点的距离和

					  所以,处理好后,只要求两次源点到各点距离和相加即可

	

	精髓:静态邻接表 !!!!

	      头一次接触这个东西,代码几乎是看着别人的写出来的,自己也有少许优化

		  很给力的东西,尤其是 逆向实现链表的传递,收获不小

*/











#include <iostream>

using namespace std;

const int MAX = 1000001;

const int inf = INT_MAX;//!!!!!!!!!!1!!!!!!!!!!

int N,m,n;



typedef struct vol

{

	int w,//当前位置

		v,//价值 value

		next;//下一结点的位置

} Voll;

Voll peo[MAX],rev[MAX];



int start1[MAX], start2[MAX];

int queue[MAX];  //优化序列

int path[MAX];   // path[i] 从1即到i当前最短路



__int64 SPFA( Voll peor[], int startt[])

{



	int i,start=0,end=1,temp;

	temp = 1;

	for(i=0;i<n+1;i++)

	{

		path[i] = inf;

	}

	

	path[temp] = 0;

	queue[0] = temp;



	while(start<end)

	{

		temp = queue[start];

		start++;



		for(i=startt[temp]; i!=-1; i=peor[i].next)

		{

			if(peor[i].v + path[temp] < path[peor[i].w])

			{

				path[peor[i].w] = peor[i].v + path[temp];

				queue[end++] = peor[i].w;

			}

		}

	}

	//

	__int64 sum=0;

	for(i=1;i<=n;i++)

	{

		sum+=path[i];

	}

	return sum;

}



void init()

{

	scanf("%d %d", &n, &m);

	int i,x,y,v;



	fill(start1, start1 + n+1, -1);//应该是 n+1!!!!!   - -!

	fill(start2, start2 + n+1, -1);

	

	for(i=0;i<m;i++)

	{

		scanf("%d %d %d",&x,&y,&v);



		peo[i].w = y;

		peo[i].v = v;

		peo[i].next = start1[x];   //保存邻接表串的始端位置,逆向实现相当给力!!!

		start1[x] = i;			   

		

		///reverse反向

		rev[i].w = x;

		rev[i].v = v;

		rev[i].next = start2[y];

		start2[y] = i;

	}

}



int main()

{

	scanf("%d", &N);

	while(N--)

	{

		init();	

		printf("%I64d\n", SPFA(peo, start1) + SPFA(rev, start2));

	}

	return 0;

}





你可能感兴趣的:(SPFA)