Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

SPFA果然很嚣张。。

Posted by Ruby931031 at 2012-07-12 01:37:16 on Problem 3259 and last updated at 2012-07-12 01:37:43
In Reply To:关于Bellman-Ford算法的bug Posted by:Ruby931031 at 2012-03-21 17:49:36
SPFA()果然更快。。
//125ms
#include <stdio.h>	//链式前向星 + SPFA
#include <string.h>
#define MAXN 800
#define MAXM 3000
#define INF (1<<30)

struct Edge{
	int to,next,w;
} edge[MAXM<<1];
int head[MAXN],dist[MAXN],q[MAXM<<10],outq[MAXN],n,m,w;
bool inq[MAXN];

bool SPFA(){
	int i,iq,k,top;
	for (i=1; i<=n; ++i) {			//直接将其他所有节点入队
		dist[i]=outq[i]=0;
		q[i]=i;
		inq[i]=true;
	}

	i=1,iq=n+1;
	while (i!=iq){
		inq[ top=q[i] ] = false;
		if ( ++outq[top] > n )		return true;
		for ( k=head[top]; k!=-1; k=edge[k].next )
			if ( dist[edge[k].to] > dist[top] + edge[k].w ) {

				dist[edge[k].to] = dist[top] + edge[k].w;
				if ( !inq[edge[k].to] ) {
					inq[ edge[k].to ] = true;
					q[iq++] = edge[k].to;
				}
			}
		++i;
	}
	return false;
}

int main()
{
	int f,i,s,e,t,tot;
	scanf("%d",&f);
	while (f--){
		memset(head,-1,sizeof(head));
		scanf("%d %d %d", &n, &m, &w);
		for (tot=i=0; i<m; ++i){	//读入普通边
			scanf("%d %d %d", &s, &e, &t);
			edge[tot].to = e;		//无向边存两遍
			edge[tot].w = t;
			edge[tot].next = head[s];
			head[s] = tot++;

			edge[tot].to = s;
			edge[tot].w = t;
			edge[tot].next = head[e];
			head[e] = tot++;
		}
		for (i=0; i<w; ++i){		//读入虫洞
			scanf("%d %d %d", &s, &e, &t);
			edge[tot].to = e;
			edge[tot].w = -t;
			edge[tot].next = head[s];
			head[s] = tot++;
		}
		if ( SPFA() )		printf("YES\n");		//对超级源点0调用SPFA算法
		else	printf("NO\n");
	}
	return 0;
}

//下面这个循环队列157ms..
bool SPFA(){
	int i,iq,k,top,end=(n<<1)+1;	//使用循环队列q[1..2n]
	for (i=1; i<=n; ++i) {			//直接将其他所有节点入队
		dist[i]=outq[i]=0;
		q[i]=i;
		inq[i]=true;
	}

	i=1,iq=n+1;
	while (i!=iq){		//队列的范围是[i..iq)
		inq[ top=q[i] ] = false;
		if ( ++outq[top] > n )		return true;
		for ( k=head[top]; k!=-1; k=edge[k].next )
			if ( dist[edge[k].to] > dist[top] + edge[k].w ) {

				dist[edge[k].to] = dist[top] + edge[k].w;
				if ( !inq[edge[k].to] ) {
					inq[ edge[k].to ] = true;
					q[iq++] = edge[k].to;
					if (iq==end)	iq=1;
				}
			}
		if (++i == end)		i=1;
	}
	return false;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator