山再高,往上爬,總能登頂;
路再長,走下去,定能到達。
選地址
題目描述
小X有很多朋友、、分佈在N個城市。。
這N個城市之間,有些有直接的道路,有些是間接聯通的(保證任何兩個城市都可以相互到達。。)
但是、經過每條道路都是有代價的、、
於是。。
小X希望你來幫他找出一個城市,使得他的所有朋友到這個城市的代價最小。
輸入
輸入共2N+1行,
其中第一行爲一個整數N、
第2~N+1行
每行有N個整數、表示兩個城市間的代價、(0表示不直接連通)
第n+2~2N+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-輪月