题目链接
原标题:Qin Shi Huang’s National Road System
CSDN把System设置成非法字符?
题意
个城市每个城市有一定的人口,秦始皇要修地铁了。他的手下运用魔法之后可以让一条路的代价为0,秦始皇想知道在那条路上运用魔法可以使得 最大
思路
- 修路的花费尽量小
- 选择路两端的人口总数尽量大
先求最小生成树然后判断每条边,如果这条边是最小生成树上的边
ans =
, 如果这条边不是最小生成树上的一条边,我们需要构造一个次小生成树,然后类似的求出最大值,中间不断更新
即可。
218MS 32720K,空间勉强卡过,
的内存成倍扩大。。
124MS 10268K
29061190 2019-04-26 11:45:53 Accepted 4081 2420 B G++ henuyh
// prim
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn = 1001;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;
int n, m;
struct ac{
int u, v, w;
ac(int u_=0, int v_=0, int w_=0){
u = u_; v = v_; w = w_;
}
inline int Dis(ac x) {
return ((x.u-u)*(x.u-u) + (x.v-v)*(x.v-v));
}
};
int g[maxn][maxn], val[maxn], vis[maxn], dis[maxn];
int pre[maxn], maxd[maxn][maxn];
bool used[maxn][maxn];
double Count(int i, int j, double sum) {
return (val[i] + val[j]) * 1.0 / (sum - sqrt(g[i][j]));
}
void prim(int s) {
mem(maxd, 0);
mem(vis, 0);
mem(used, 0);
for (int i = 0; i < n; ++i) {
dis[i] = g[s][i];
pre[i] = s;
}
vis[s] = 1;
double sum = 0;
for (int i = 1; i < n; ++i) {
int u = -1, MIN = inf;
for (int j = 0; j < n; ++j) {
if (vis[j]) continue;
if (MIN > dis[j]) {
MIN = dis[j];
u = j;
}
}
if (u == -1) break;
vis[u] = 1;
sum += sqrt(MIN);
used[pre[u]][u] = used[u][pre[u]] = 1;
maxd[u][pre[u]] = maxd[pre[u]][u] = MIN;
for (int j = 0; j < n; ++j) {
if (j == u) continue;
if (vis[j]) {
maxd[u][j] = maxd[j][u] = max(maxd[pre[u]][j], MIN);
}
if (vis[j] == 0 && dis[j] > g[u][j]) {
dis[j] = g[u][j];
pre[j] = u;
}
}
}
double ans = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (used[i][j]) ans = max(ans, Count(i, j, sum));
else ans = max(ans, Count(i, j, sum - sqrt(maxd[i][j]) + sqrt(g[i][j])));
}
}
printf("%.2lf\n", ans);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
vector<ac> t(n);
mem(g, inf);
for (int i = 0; i < n; ++i) {
scanf("%d%d%d", &t[i].u, &t[i].v, &val[i]);
}
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
g[i][j] = g[j][i] = t[i].Dis(t[j]);
}
}
prim(0);
}
return 0;
}
// kruskal
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn = 1e3 + 1;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;
struct ac{
int u, v, flag;
double w;
ac(int u_=0, int v_=0, double w_=0, int flag_=0){
u = u_; v = v_; w = w_; flag = flag_;
}
bool operator <(ac t) {
return w < t.w;
}
}g[1000001];
vector<int> son[maxn];
int pre[maxn], val[maxn];
double dis[maxn][maxn];
int find (int x) {
return (pre[x] == x) ? x : pre[x] = find(pre[x]);
}
int n, m;
double Dis(ac x, ac y) {
return sqrt((x.u-y.u)*(x.u-y.u) + (x.v-y.v)*(x.v-y.v));
}
double Count(double all, ac t) {
return (val[t.u] + val[t.v]) * 1.0 / (all - t.w);
}
void Kruskal() {
for (int i = 0; i <= n; ++i) {
son[i].clear();
son[i].push_back(i);
pre[i] = i;
}
sort(g, g+m);
double sum = 0;
int cnt = 0;
for (int i = 0; i < m; ++i) {
if (cnt == n+1) break;
int fx = find(g[i].u);
int fy = find(g[i].v);
if (fx == fy) continue;
g[i].flag = 1;
sum += g[i].w;
cnt++;
int lenx = son[fx].size();
int leny = son[fy].size();
if (lenx < leny) {
swap(lenx, leny);
swap(fx, fy);
}
for (int j = 0; j < lenx; ++j) {
for (int k = 0; k < leny; ++k) {
dis[son[fx][j]][son[fy][k]] = dis[son[fy][k]][son[fx][j]] = g[i].w;
}
}
pre[fy] = fx;
for (int j = 0; j < leny; ++j) {
son[fx].push_back(son[fy][j]);
}
son[fy].clear();
}
double ans = -1;
for (int i = 0; i < m; ++i) {
if (g[i].flag) {
ans = max(ans, Count(sum, g[i]));
}else {
ans = max(ans, Count(sum + g[i].w - dis[g[i].u][g[i].v], g[i]));
}
}
printf("%.2lf\n", ans);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
vector<ac> t(n);
for (int i = 0; i < n; ++i) {
scanf("%d%d%d", &t[i].u, &t[i].v, &val[i]);
}
m = 0;
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
g[m++] = ac(i, j, Dis(t[i], t[j]), 0);
}
}
Kruskal();
}
return 0;
}