POJ 1511 Invitation Cards (ZOJ 2008) 使用优先队列的dijkstra

94 篇文章 0 订阅
50 篇文章 0 订阅

传送门:

http://poj.org/problem?id=1511

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1008


题目大意:

给定p个点,还有他们的边q,(有向图)求从结点1出发到所有结点和所有结点到1的最短路径之和。

其中1 <= P,Q <= 1000000


思路:

和上次 POJ 3268 Silver Cow Party 一样,有向图倒着建立就把从所有结点到1的最短路径改为了从1到所有,那么只需两次dijkstra即可。

还有就是数据量大,要用优先队列的dijkstra,堆优化的更好。

嗯,第一次写这个,参考了别人的。

code1:2014/1/1更新。。。

今天自己写的------

直接用数组模拟链表快了好多,zoj排名挺靠前面的,嘻嘻,不过poj又被虐。。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1000000+10;
bool vis[MAXN];
int head[2][MAXN];
int n,m;
long long ans;
struct edge
{
	int to;
	int cost;
	int next;
}e[2][MAXN];

struct node
{
	int from;
	int cost;
	node(int f,int c){from=f;cost=c;}
	bool operator < (const node& b)const
	{
		return cost > b.cost;
	}
};

int len;
void insert(int from,int to,int cost)
{
	e[0][len].to=to;      
	e[1][len].to=from;
	
	e[0][len].cost=e[1][len].cost=cost;
	
	e[0][len].next = head[0][ from ];
	e[1][len].next = head[1][ to ];

	head[0][from]=len;
	head[1][to]=len;

	len++;
}

void dijkstra(int kind)
{
	memset(vis,0,sizeof(vis));
	priority_queue<node> q;
	q.push(node(1,0));
	
	int num=0;
	while(!q.empty())
	{
		node cur=q.top();
		q.pop();

		if(vis[cur.from]==true)  continue; 

		vis[cur.from]=true;
		ans+=cur.cost;
		num++;

		if(num==n)
			break;
		
		//这里写得真纠结- -|||
		
		for(int ne=head[kind][cur.from];ne!=-1;ne=e[kind][ ne ].next)
		{
			if(!vis[e[kind][ ne ].to])		
				q.push(node(e[kind][ ne ].to,e[kind][ ne ].cost+cur.cost));		
		}
	}
}

int main()
{
	int T;
	scanf("%d",&T);
	int from,to,cost;
	while(T--)
	{
		len=0;
		memset(head,-1,sizeof(head));
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&from,&to,&cost);
			insert(from,to,cost);
		}
		ans=0;
		dijkstra(0);
		dijkstra(1);
		printf("%lld\n",ans);
	}
	return 0;
}


code 2:

2013/12/31第一次写,基本上是模仿别人的


#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1000000+10;
long long ans;
bool vis[MAXN];
int n,m;
struct edge
{
	int to,cost;
	edge* next;
	edge(){next=NULL;}
}*e[2][MAXN];

struct node
{
	int cost,id;
	bool operator < (const node& b)  const
    {  
        return cost>b.cost;    
    }  
	node(int i,int c){ cost =c;id=i;}
};

inline void addedge(int from,int to,int cost)
{
	edge *p=new edge;
	edge *q=new edge;

	p->next=e[0][from];
	q->next=e[1][to];

	p->to=to;
	q->to=from;

	p->cost=q->cost=cost;

	e[0][from]=p;
	e[1][to]=q;
}

void dijkstra(int kind)
{
	memset(vis,0,sizeof(vis));
	priority_queue<node> q;
	int num=0;
	node cur(1,0);
	q.push(cur);
	while(!q.empty())
	{
		cur=q.top();
		q.pop();
		if(vis[cur.id]==true)
			continue;
		
		vis[cur.id]=true;
		ans+=cur.cost;
		num++;
		if(num==n)
			break;
		
		for(edge *p=e[kind][cur.id];p!=NULL;p=p->next)
		{		
			if(vis[p->to]==false)
			{
				node temp(p->to,p->cost+cur.cost);
				q.push(temp);
			}
		}
	}


}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		memset(e,NULL,sizeof(e));  
 
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++)
		{
			int from,to,cost;
			scanf("%d%d%d",&from,&to,&cost);
			addedge(from,to,cost);
		}
		ans=0;
		dijkstra(0);
		dijkstra(1);
		printf("%lld\n",ans);
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值