UPC-選地址(Floyd)

山再高,往上爬,總能登頂;
路再長,走下去,定能到達。

選地址

題目描述

小X有很多朋友、、分佈在N個城市。。
這N個城市之間,有些有直接的道路,有些是間接聯通的(保證任何兩個城市都可以相互到達。。)
但是、經過每條道路都是有代價的、、
於是。。
小X希望你來幫他找出一個城市,使得他的所有朋友到這個城市的代價最小。

輸入

輸入共2N+1行,
其中第一行爲一個整數N、
第2~N+1行
每行有N個整數、表示兩個城市間的代價、(0表示不直接連通)
第n+2~2
N+1行
每行一個整數。表示每個城市中小X的朋友數。

輸出

輸出有兩行。
第一行爲你選中的城市
第二行爲最小需要的代價。

Sample Inout

5
0 1 2 0 0
1 0 0 0 20
2 0 0 10 0
0 0 10 0 1
0 20 0 1 0
2
3
4
5
6

Sample Output

4
109

Hint

對於100%的數據,n<=200,輸出保證不超過long long int

思路分析
這題考察的是查詢最短路徑,可以用Dijkstra來查詢每一個路徑,然後查詢全部。或者用Floyd查詢多元最短路

Floyd算法基礎應用就這麼幾步
第一將所有邊設成無窮大。注意這裏不能設的非常大,因爲如果太大那麼d[i][k]+d[k][j]可能會溢出。
第二構造邊。自己對自己設成0(如果自己和自己的對應一點關係都沒有的話,設成INF也沒問題),其餘該多少是多少,無窮大爲不連通。
第三步Floyd算法的核心步驟,枚舉中間點,尋找兩點間的最短路徑

#define Floyd for(int k = 1; k <= n; k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)

咱們常用的寫法是

for (int k = 1; k <= n; k++)
				for (int i = 1; i <= n; i++)
					for (int j = 1; j <= n; j++)
						d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

前面三個沒有什麼靈活性直接將其宏定義即可
再然後每兩個點之間的最短路徑都給尋找出來了,複雜度O(n^3)
然後就讓每個點都試一下可不可做中心城市,求最終結果就可以了

AC時間到

#include<algorithm>
#include<iostream>
#include<string.h>
#include<utility>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#pragma warning(disable:4244)
#define PI 3.1415926536
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
ll GCD(ll a, ll b) { return a ? GCD(b, a % b) : a; }
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a)
{
	if (a < 0)putchar('-'), a = -a;
	if (a >= 10)out(a / 10);
	putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod; n >>= 1;
	}
	return res;
}
#define Floyd for(int k = 1; k <= n; k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
#define read read()
ll d[300][300];
int save[300];
int main()
{
	memset(d, 0x3f3f3f3f, sizeof(d));//0x3f3f3f3f設成INF
	ll INF = d[0][0];
	ll n = read;
	for (int i = 1; i <= n; i++)//自己到自己設成0,此外不通的均爲INF
	{
		for (int j = 1; j <= n; j++)
		{
			ll temp = read;
			if (temp)d[i][j] = temp;
		}
		d[i][i] = 0;
	}//Floyd
	Floyd d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	ll id = 0, ans = ll_inf;//初始話id 和ans
	for (int i = 1; i <= n; i++)save[i] = read;//小盆友
	for (int i = 1; i <= n; i++)
	{
		ll sum = 0;
		for (int j = 1; j <= n; j++)
		{
			if (d[j][i] == INF)goto END;//如果不連通直接下一個
			sum += d[j][i] * save[j];
		}
		if (sum < ans)//改變
		{
			ans = sum;
			id = i;
		}
	END:;
	}
	cout << id << '\n' << ans << endl;
}

By-輪月

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