九度oj-最短路徑問題

totoroer發表於2018-03-27

題目描述:

給你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;
}

 

 

 

 

相關文章