[傳智杯 #2 決賽] 傳送門

糊涂不再糊涂發表於2024-07-09

https://www.luogu.com.cn/problem/P6464?contestId=180677
傳智專修學院裡有
n 棟教學樓,有 m 條雙向通行道路連線這些教學樓,不存在重邊和自環。每條道路都有一定的長度,而且所有教學樓之間都可以直接或者間接的透過道路到達。我們可以很容易的求出這些教學樓之間的最短路。
為了使交通更為順暢,校方決定在兩個教學樓裡增設一對傳送門。傳送門可以將這對教學樓的距離直接縮短為 0。利用傳送門,某些教學樓之間的最短路的距離就變短了。
由於預算有限,學校裡只能安裝一對傳送門。但是校長希望儘可能方便學生,使任意兩點之間的最短路長度的總和最小。當然啦,從 x 教學樓到 y 教學樓的長度和從 y 教學樓到 x 教學樓的長度只需要統計一次就可以了。
上述便是題目,簡單來說就是學院有n個教學樓,教學樓上一共有m條通道這些通道可以互通,但是有一個傳送門可以直接將這一棟的人傳送到另一棟上面,傳送的權值為0,求出有有傳送門的情況下去完每棟樓最少要走的路是多少
由題意可知上述題目是使用floyd演算法和列舉法來解決書取得該多元的最小值,我們假定一個座標,我們在一號樓然後我們把傳送門放在二號樓來算出此時的最短路,再將傳送門放在三號樓算出最短路等一號樓的這種情況算完了我們再從二號樓開始
以此類推得出結論

點選檢視程式碼
`#include<bits/stdc++.h>
using namespace std;
int to[100000],mp[5000][5000] //建立變數來進行儲存;
int main() {
	int n, m, a, b, c;
	cin >> n >> m;
	for(int i = 1; i<= n; i++) {
		for(int j = 1;  j<= n; j++) {
			if(i==j)mp[i][j]=0;
			else mp[i][j]=1e8//進行初始化這樣子才能使得接下來的想法中找到最小值;
            //否則預設mp為0會導致結果出現錯誤
		}
	}
	for(int i = 1; i <= m; i++) {
		cin >> a >> b >> c;
		if(mp[a][b] > c) {
			mp[a][b]=c;
			mp[b][a]=c;//因為是雙向邊所以都要進行記錄
		}

	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1;  i<= n; i++) {
			for(int j = 1;  j <= n; j++) {
				mp[i][j]=min(mp[i][j],mp[k][j]+mp[i][k]);//這個地方為正常的floyd演算法題目所用的比這個稍微複雜一些 
			}
		}
	}
	long long t = 0,ans=INT_MAX;
	for(int men=1; men<n;men++) {//傳送門所在的樓是哪棟
		for(int k = men+1; k <= n; k++) {//為什麼要加一,假設men=k傳送門無意義但這樣子可以稍微減少時間複雜度
			t=0;
			for(int i = 1;  i< n; i++) {//開始遍歷起點到哪個終點的路徑
				for(int j = i+1;  j <= n; j++) {
					if(men!=i||j!=k)//出發點等於傳送門的位置和跳躍點等於直接到的地方這樣子無意義.
					t+=min(mp[i][j],min(mp[men][j]+mp[k][i],mp[men][i]+mp[k][j]));//開始比較將起點到跳躍點,跳躍點從傳送門傳過去和起點到傳送門,傳送門再到跳躍點的值再到我要的終點進行比較選出權值
                      //小的那一個並比較和直接過去的權值比
				}
			}
			ans=min(ans,t);//選出權值最小的那一個進行比較與記錄
		}
	}
	cout <<ans<< endl;
	return 0;
}`

相關文章