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-轮月

发布了39 篇原创文章 · 获赞 15 · 访问量 1836

猜你喜欢

转载自blog.csdn.net/qq_35339563/article/details/105316664
UPC
今日推荐