山再高,往上爬,总能登顶;
路再长,走下去,定能到达。
选地址
题目描述
小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-轮月