九度oj-最短路径问题

题目描述:

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

输入:

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)

输出:

输出 一行有两个数, 最短距离及其花费。

样例输入:

 

3 2
1 2 5 6
2 3 4 5
1 3
0 0

样例输出:

 

9 11

题目分析:

题目本身不难,编写时细心一点!

主要学习一下图的邻接链表表示。

有几点需要注意:由于图是无向的,所以在用链表存储的时候记得把b也push进去

# include<stdio.h>
# include<vector>
using namespace std;
# define N 10001
struct edge
{
	int next;//下一个顶点
	int length;//两个顶点之间的边长
	int cost;//两个顶点之间的代价
};

int main()
{
	int n,m;
	vector<edge> ed[N];
	bool mark[N];//判断当前点是否已经被遍历
	int dis[N];//最短距离
	int minCost[N];//最短距离对应的代价
	int i,j,k;
	
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		if(n==0&&m==0)
			break;
		//初始化
		for(i=1;i<=n;i++)
		{
			ed[i].clear();
		}
		
		while(m--)
		{
			int a,b,len,cos;
			scanf("%d%d%d%d",&a,&b,&len,&cos);
			edge tmp;
			tmp.next=b;
			tmp.length=len;
			tmp.cost=cos;
			
			ed[a].push_back(tmp);
			
			tmp.next=a;
			ed[b].push_back(tmp);//记得把b也push进去
		}
		
		int S,T;
		scanf("%d%d",&S,&T);
        
		//初始化
		for(i=1;i<=n;i++)
		{
			mark[i]=false;
			dis[i]=-1;
			minCost[i]=0;
		}
		
		mark[S]=true;
		dis[S]=0;
		int newP=S;	
		for(i=1;i<n;i++)//对剩余的n-1个顶点遍历
		{
			for(j=0;j<ed[newP].size();j++)//对s的邻接遍历
			{
				int t=ed[newP][j].next;
				int le=ed[newP][j].length;
				int co=ed[newP][j].cost;
				
			//	printf("%d\n",t);
				if(mark[t]==true)
					continue;
				if(dis[t]==-1||dis[t]>dis[newP]+le||(dis[t]==dis[newP]+le&&minCost[t]>minCost[newP]+co))
				{//这个地方容易漏掉一种情况,就是最短路径相同时需要对对应的时间做判断
					dis[t]=dis[newP]+le;
					minCost[t]=minCost[newP]+co;
				}
			}
			//寻找下一个要遍历的点,全局搜索
            int	min=10000000;
			for(k=1;k<=n;k++)
			{
				if(mark[k]==true)
					continue;
				if(dis[k]==-1)
					continue;
				if(dis[k]<min)
				{
					min=dis[k];
					newP=k;
				}
			}
			mark[newP]=true;	
		}	
		printf("%d %d\n",dis[T],minCost[T]);
	}
	
	return 0;
}

 

 

 

 

posted @ 2018-03-27 10:33  xzhws  阅读(46)  评论(0编辑  收藏  举报