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


posted @ 2011-01-19 18:16  kfinder  阅读(477)  评论(0编辑  收藏  举报