POJ 1511 Invitation Cards (SPFA)

这题思路和POJ 3268 是基本一样的,但数据规模很大,应当做如下处理:

数组要开大

SPFA若不用循环队列则队列要到10的七次方才比较稳妥

储存权值的空间要开成LONG LONG

就可以过了。

#include <stdio.h>
#include <string.h>
#define MAXN 1000000
#define MAXM MAXN
#define inf 1000000000000000000    //18

int head[2][MAXN], pnt[2][MAXM], next[2][MAXM];

long long length[2][MAXM];

int tot[2];

long long dist[2][MAXN];

int queue[10000000];
int inq[MAXN];
int countq[MAXN];

int n,m,x;
int a,b;
long long len;

void addedge(int func,int a,int b,long long len)
{
	pnt[func][tot[func]]=b;
	length[func][tot[func]]=len;
	next[func][tot[func]]=head[func][a];
	head[func][a]=tot[func]++;
}

int spfa(int func)
{
	int qhead=0;
	int qtail=1;
	
	for (int i=0; i<n; i++) {
		inq[i]=0;
		countq[i]=0;
		dist[func][i]=inf;
	}
	dist[func][0]=0;
	
	queue[qhead]=0;
	
	while (qhead<qtail) {
		int idx=head[func][queue[qhead]];
		while (~idx) {
			if(dist[func][queue[qhead]] + length[func][idx] < dist[func][pnt[func][idx]]) {
				dist[func][pnt[func][idx]] = dist[func][queue[qhead]] + length[func][idx];
				if(!inq[pnt[func][idx]]) {
					inq[pnt[func][idx]]=1;
					countq[pnt[func][idx]]++;
					if(countq[pnt[func][idx]] > n+1) return 0;
					queue[qtail++]=pnt[func][idx];
				}
			}
			idx=next[func][idx];
		}
		inq[queue[qhead]]=0;
		qhead++;
	}
	return 1;
}

int main()
{
	int ncase;
	scanf("%d",&ncase);
	while (ncase--) {
		scanf("%d%d",&n,&m);
	
		for(int i=0; i<2; i++) {
			for (int j=0; j<n; j++) {
				head[i][j]=-1;
			}
			for (int j=0; j<m; j++) {
				next[i][j]=-1;
			}
			tot[i]=0;
		}
	
		for(int i=0; i<m; i++) {
			scanf("%d%d%lld",&a,&b,&len);
			addedge(0,a-1,b-1,len);
			addedge(1,b-1,a-1,len);
		}
	
		spfa(0);
		spfa(1);
		long long ans=0;
		for(int i=1;i<n;i++) {
			ans+=dist[0][i]+dist[1][i];
		}
	
		printf("%lld\n",ans);
	}
}

  

posted on 2011-07-23 22:34  Eucalyptus  阅读(198)  评论(0编辑  收藏  举报