您的位置:首页 > 其它

CDOJ 1146 秋实大哥与连锁快餐店 Prim 最小生成树

2016-07-31 19:25 351 查看
嗯,题意就是说,平面坐标系上有n个点,它们可以形成一个完全图,距离就是两点的欧几里德距离

然后其中有一些点是旗舰店,然后现在想连一些边,使得所有的点都与至少一个旗舰店连通,然后问最小的边权和

显然就是最小生成树了

但是这是稠密图(其实我觉得即使稠密图,Kruskal的表现应该也很好,因为并查集部分的操作应该是近乎常数的吧),所以prim会更好

开始时用的Kruskal,直接MLE了,发现是内存限制比较小,然后也就放弃了堆优化 的prim,直接上普通的prim,然后就过了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <fstream>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define maxn 6700
#define maxm 23000000
pair<ll, ll> node[maxn];
int n;
bool root[maxn];
ll dist[maxn];
double Prim()
{
double ans = 0;
bool flag = true;
ll tmp;
for (int i = 0; i < n; ++i)
{
if (!root[i])
continue;
if (flag)
{
for (int j = 0; j < n; ++j)
{
dist[j] = (node[i].first - node[j].first)*(node[i].first - node[j].first) + (node[i].second - node[j].second)*(node[i].second - node[j].second);
}
flag = false;
}
else
{
for (int j = 0; j < n; ++j)
{
tmp = (node[i].first - node[j].first)*(node[i].first - node[j].first) + (node[i].second - node[j].second)*(node[i].second - node[j].second);
if (tmp < dist[j])
dist[j] = tmp;
}
}
}
for (int i = 0; i < n; ++i)
{
int k = -1;
ll minv = 999999999999999;
for (int j = 0; j < n; ++j)
{
if (!root[j] && dist[j] < minv)
{
k = j; minv = dist[j];
}
}
if (k == -1)
break;
root[k] = true;
ans += sqrt(minv);
for (int j = 0; j < n; ++j)
{
if (!root[j])
{
tmp = (node[k].first - node[j].first)*(node[k].first - node[j].first) + (node[k].second - node[j].second)*(node[k].second - node[j].second);
if (tmp < dist[j])
{
dist[j] = tmp;
}
}
}
}
return ans;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//ifstream in;
//in.open("input.txt", ios::in);
scanf("%d", &n);
int tmp;
for (int i = 0; i < n; ++i)
{
scanf("%lld%lld%d", &node[i].first, &node[i].second, &tmp);
if (tmp > 0)
root[i] = true;
}
double ans;
ans = Prim();
printf("%.2f\n", ans);
//while (1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: