poj 1511 Invitation Cards

题目地址:http://poj.org/problem?id=1511

方法一:

/*
	本题使用邻接表采用动态开辟的方式保存所有的边,首先定义一个保存指向的顶点和边所对应权值,
*/
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define NMAX_D 1000005
#define NMAX 1000000001
int n,m;
//定义结构体
struct node
{
	int v,cost;
	node *next;
}edge[NMAX_D],redge[NMAX_D];//定义两个数组,edge用来保存顺向边,redge保存逆向边
bool vis[NMAX_D];//标记数组,用来标记结点i是否已经在队列里面,防止重复对同一节点进行扩展
int dis[NMAX_D];//保存起点到目标结点的距离
__int64 sum;//用来保存总的费用,显然最后结果很可能超int
queue<int> Q;
void release(node edge[])//初始化结点,分离出所有结点
{
	node *p,*q;
	for(int i = 1; i <= n; i++)
	{
		p = &edge[i];
		while(p->next)
		{
			q = p->next;
			p->next = q->next;
			free(q);
		}
	}
}
void init()//输入各边关系和边所对应的权值。并构造邻接表
{
	int a,b,c;
	node *p,*q;
	release(edge);
	release(redge);
	for(int i = 0; i < m;i++ )
	{
		scanf("%d%d%d",&a,&b,&c);
		q = (node*)malloc(sizeof(node));
		q->v = b;
		q->cost = c;
		p = &edge[a];
		q->next = p->next;
		p->next = q;


		q = (node*)malloc(sizeof(node));
		q->v = a;q->cost = c;
		p = &redge[b];
		q->next = p->next;
		p->next = q;
	}
}

//spfa算法,求最短路径
void psfa(node edge[])
{
	int i;
	//初始化数组vis和数组dis
	memset(vis,false,sizeof(vis));
	for(i = 0; i <= n; i++)
		dis[i] = NMAX;
	dis[1] = 0;
	vis[1] = true;//标记1号结点已经在队列中
	Q.push(1);//第一个顶点进队列
	while( !Q.empty())
	{
		int now = Q.front();//取队头元素
		Q.pop();//队头元素出队列
		vis[now] = false;//标记now结点为不在队列中
		for(node *p = edge[now].next; p ; p = p->next)
		{
			if(dis[p->v] > dis[now] + p->cost)//求当存在大结点p->v更短的路径时,更新从起点到p->v的路径
			{
				dis[p->v] = dis[now] + p->cost;
				if(!vis[p->v])//当结点p->v已经在队列中则不再进队列
				{
					vis[p->v] = true;
					Q.push(p->v);
				}
			}
		}
	}
	for(i = 1; i <= n; i++)sum += dis[i];
}
int main()
{
	int t;
	scanf("%d",&t);
	while( t-- )
	{
		scanf("%d%d",&n,&m);
		init();
		sum = 0;
		psfa(edge);
		psfa(redge);
		printf("%I64d\n",sum);
	}
	return 0;
}


方法二:

用SPFA,又加了点优化用SLF。

/*
	采用邻接表的变形版本保存,用两个指针数组保存结点,用一个连续的一维数组保存边,
	起于同一顶点的边用指针连接。
*/
#include<stdio.h>
#include<string.h>
#include<deque>
using std::deque;
#define INF (1<<30)
#define MAXN 1000001
//用来保存数据的结构体
struct node
{
	int v,cost;
	node *next;
};
//*head1[]和*head[]均为保存结点的指针数组,edge,和redge两个数组用来保存
node *head1[MAXN],*head[MAXN],edge[MAXN],redge[MAXN],*p1,*q1;

int n,m,dis[MAXN];
bool vis[MAXN];
deque<int>Q;
__int64 sum;
void init()
{
	int i,a,b,c;
	p1 = edge,q1 = redge,sum = 0;
	for(i = 0; i <= n; i++)head1[i] = head[i] = NULL;
	for(i = 0; i < m; i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		p1->v = b;p1->cost = c;
		p1->next = head[a];
		head[a] = p1++;

		q1->v = a;q1->cost = c;
		q1->next = head1[b];
		head1[b] = q1++;
	}
}
void spfa(bool is)
{
	int i ;
	memset(vis,false,sizeof(vis));
	for(i = 2; i <= n; i++)dis[i] = INF;
	dis[1] = 0;
	vis[1] = true;
	Q.push_front(1);
	while( !Q.empty() )
	{
		int now = Q.front();
		Q.pop_front();
		vis[now] = false;
		for(p1 = (is) ? head[now] : head1[now] ; p1; p1 = p1->next)
		{
			if(dis[p1->v] > dis[now] +p1->cost)
			{
				dis[p1->v] = dis[now] + p1->cost;
				//p1->v进队列
				if( !Q.empty() && dis[p1->v] < dis[Q.front()])
					Q.push_front(p1->v);
				else
					Q.push_back(p1->v);
				vis[p1->v] = true;
			}
		}
	}
	for(i = 1; i <= n; i++)sum += dis[i];
}
int main()
{
	int t;
	scanf("%d",&t);
	while( t-- )
	{
		scanf("%d%d",&n,&m);
		init();
		spfa(true);
		spfa(false);
		printf("%I64d\n",sum);
	}
	return 0;
}


 

原文地址:https://www.cnblogs.com/LUO257316/p/3220865.html