poj 1847最短路



题意:n个点,电车从A到B。每个点可以到其它ki个点,但默认只通往给出的第一个点,如果要到其它点,必须改变轨道方向一次。问A到B最少改变几次轨道方向。



总结:裸裸的最短路,所以,狠狠的把Floyd, Bellman, Dijkstra, Spfa都给撸了一遍。一个字,爽!


一道裸体,题意比较坑,于是试着写了一发dij的优先队列优化(V*log(E))和flyd。


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define LL int
const int MAX=1000000000;
int n,A,B;
int mat[200][200];

struct node{
	LL x,d;
	node(LL a,LL b){ x=a,d=b;}
	bool operator <(const node &a) const 
	{
		if(d==a.d) return x>a.x;
		return a.d<d;
	}
}; 
vector<node>p[200]; 
void init()
{
   for(int i=0;i<200;i++)	p[i].clear();
	for(int i=0;i<=n;i++)
	{
	
		for(int j=0;j<=n;j++)
		{
			if(i==j) mat[i][j]=0;  //自身点初始化为0 
			else
		 mat[i][j]=MAX;
		}
	}
}
int floyd()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=n;k++)
			{
				mat[j][k]=min(mat[j][k],mat[j][i]+mat[i][k]);    //以最外成作为松弛点 
			}
		}
	}
	if(mat[A][B]>=MAX) return -1;
	else return mat[A][B];
}

int Dijkstra()
{
	int dis[200];
	for(int i=0;i<=n;i++) dis[i]=MAX;
	dis[A]=0;
	priority_queue<node>q;
	q.push(node(A,dis[A]));
	while(!q.empty())
	{
		node x=q.top();
		q.pop();
		for(int i=0;i<p[x.x].size();i++)
		{
			node y=p[x.x][i];
			if(dis[y.x]>x.d+y.d)
			{
				dis[y.x]=x.d+y.d;
				q.push(node(y.x,dis[y.x]));
			}
		}
	}
//	for(int i=0;i<=n;i++) printf("%d  ",dis[i]);
	if(dis[B]==MAX) return -1;
	else return dis[B];
	
}
int main()
{
	while(scanf("%d%d%d",&n,&A,&B)!=EOF)
	{
		init();
		for(int i=1;i<=n;i++)
		{
			int num;
			scanf("%d",&num);
			for(int j=1;j<=num;j++)
			{
				int end;
				scanf("%d",&end);
				if(j==1)
				{
				p[i].push_back(node(end,0));
			//	p[end].push_back(node(i,0));
				mat[i][end]=0;
				}
				else
				{
				 p[i].push_back(node(end,1));
			//	 p[end].push_back(node(i,1));
				 mat[i][end]=1;
				}
			}
		}
		int sum=0;
		//sum=floyd();
		sum=Dijkstra();
		printf("%d\n",sum);
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值