2020寒假【gmoj1504】【城市連接】【dijkstra最短路】

題目描述

天網恢恢,疏而不漏,經過上一次的抓捕,OI總部終於獲取了怪盜的特徵!現在,我們需要在基德再次來之前就把他的特徵送到超級大牛的手上,可惜超級大牛不在總部,所以飛過海必須儘快把資料送到大牛家裏。已知OI總部到大牛家中間有n-2個城城市,爲了儘快達到目的地,飛過海通過水晶球瞭解到OI總部到大牛家的路線圖,圖上顯示了n個城之間的連接距離。

可是飛過海很忙,需要請你來幫忙編寫一個程序。

輸入

輸入文件中的第一行爲一個整數n(n<=1000)。

第二行至第n+1行,每行有n個數。其中:第i+1行中表示第i個城市與其他城市之間的連接關係,0表示不連接,其它數字表示連接的距離。

輸出

輸出文件中的第一行爲n個整數,表示所選的線路。

第二行中爲一個數,表示最短距離。

樣例輸入

7
0 3 5 0 0 0 0
0 0 0 7 8 6 0
0 0 0 0 4 5 0
0 0 0 0 0 0 4
0 0 0 0 0 0 7
0 0 0 0 0 0 6
0 0 0 0 0 0 0

樣例輸出

1 2 4 7
14

分析

這題先看數據。可以用鄰接矩陣。但是floyed會超時,只能選用dijkatra,時間複雜度O(n2)。

其實這題就跟dijkstra的模板題差不多,模板熟打出來就行。但是怎樣輸出過程呢?
先建一個p數組,初始化爲-1,每當藍點變成白點的時候記錄當前的點(因爲白點一定是當前鬆弛的最短路)。最後while循環走一遍這條路,因爲是反着的,所以再開個數組記錄,順序輸出。
當然,遞歸也不是不可以。

上代碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,k,q,z;
int a[1001][1001],d[1001],p[1001],minn,pp[1001];
bool b[1001];//藍白點 
void input()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
			if(a[i][j]==0) a[i][j]=0x3fffff;
		} 
	}
}
void dijkstra()
{
	for(int i=1;i<=n;i++)
	{
		minn=0x3fffff;
		k=0;
		for(int j=1;j<=n;j++)
		{
			if((!b[j])&&(d[j]<minn))
			{
				minn=d[j];
				k=j;
			}
		}
		if(k==0) break;
		b[k]=true;
		for(int j=1;j<=n;j++)
	    {
	    	if(d[k]+a[k][j]<d[j]&&(!b[j]))
	    	{
	    		d[j]=d[k]+a[k][j];//變點
	    		p[j]=k;//記錄
	    	}
	    }
	}
} 
int main()
{
	freopen("city.in","r",stdin);
	freopen("city.out","w",stdout); 
	input();
	memset(p,-1,sizeof(p));
	for(int i=1;i<=n;i++)
	{
		d[i]=a[1][i];
	} 
    memset(b,false,sizeof(b));
    b[1]=true;
    d[1]=0;//最短路第一個設爲0;
	dijkstra(); //最短路算法;
	cout<<1<<' ';
	int nn=n,s=0;
	while(p[nn]!=-1)//輸出部分
	{
		s++;
	    pp[s]=p[nn];
		nn=p[nn];
	}
	for(int i=s;i>=1;i--)
	{
		cout<<pp[i]<<' ';
	}
	cout<<n<<endl;
	cout<<d[n];
	fclose(stdin);
	fclose(stdout);
	return 0;
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章