#1109 : 最小生成树三·堆优化的Prim算法
2015-07-27 17:20
246 查看
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
回到两个星期之前,在成功的使用Kruscal算法解决了问题之后,小Ho产生了一个疑问,究竟这样的算法在稀疏图上比Prim优化之处在哪里呢?
提示:没有无缘无故的优化!
每个测试点(输入文件)有且仅有一组测试数据。
在一组测试数据中:
第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。
接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。
对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.
对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。
对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。
样例输入
样例输出
92
题解:其实和克鲁斯卡尔的思想一样的,每次都查找最小边。由于使用了优先队列,排序了使得复杂度降为了nlogn。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF = 100005;
struct Node
{
int to;
int dis;
Node(int a,int b)
{
to = a; //邻接点
dis = b;
}
bool operator< (Node t) const //排序
{
return dis > t.dis;
}
};
vector<Node> vec[INF];
priority_queue<Node> q;
bool visited[INF];
void prime(int& ans,int n)
{
for(int i = 0;i < vec[1].size();i++) //与1相连的入队
{
q.push(vec[1][i]);
}
visited[1] = true;
for(int i = 1;i < n;i++) //n-1条边
{
while(!q.empty()) //每次找边最小的
{
Node t = q.top();
q.pop();
if(visited[t.to])
{
continue;
}
ans += t.dis;
visited[t.to] = true;
for(int j = 0;j < vec[t.to].size();j++) //更新队列
{
Node p = vec[t.to][j];
if(!visited[p.to])
{
q.push(p);
}
}
break;
}
}
printf("%d\n",ans);
for(int i = 1;i <= n;i++)
{
vec[i].clear();
}
while(!q.empty())
{
q.pop();
}
}
int main()
{
int n,m;
int u,v,dis;
cin>>n>>m;
for(int i = 0;i < m;i++)
{
scanf("%d%d%d",&u,&v,&dis);
vec[u].push_back(Node(v,dis));
vec[v].push_back(Node(u,dis));
}
memset(visited,false,sizeof(visited));
int ans = 0;
prime(ans,n);
return 0;
}
单点时限:1000ms
内存限制:256MB
描述
回到两个星期之前,在成功的使用Kruscal算法解决了问题之后,小Ho产生了一个疑问,究竟这样的算法在稀疏图上比Prim优化之处在哪里呢?提示:没有无缘无故的优化!
输入
每个测试点(输入文件)有且仅有一组测试数据。在一组测试数据中:
第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。
接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。
对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.
对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。
输出
对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。样例输入
5 29 1 2 674 2 3 249 3 4 672 4 5 933 1 2 788 3 4 147 2 4 504 3 4 38 1 3 65 3 5 6 1 5 865 1 3 590 1 4 682 2 4 227 2 4 636 1 4 312 1 3 143 2 5 158 2 3 516 3 5 102 1 5 605 1 4 99 4 5 224 2 4 198 3 5 894 1 5 845 3 4 7 2 4 14 1 4 185
样例输出
92
题解:其实和克鲁斯卡尔的思想一样的,每次都查找最小边。由于使用了优先队列,排序了使得复杂度降为了nlogn。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF = 100005;
struct Node
{
int to;
int dis;
Node(int a,int b)
{
to = a; //邻接点
dis = b;
}
bool operator< (Node t) const //排序
{
return dis > t.dis;
}
};
vector<Node> vec[INF];
priority_queue<Node> q;
bool visited[INF];
void prime(int& ans,int n)
{
for(int i = 0;i < vec[1].size();i++) //与1相连的入队
{
q.push(vec[1][i]);
}
visited[1] = true;
for(int i = 1;i < n;i++) //n-1条边
{
while(!q.empty()) //每次找边最小的
{
Node t = q.top();
q.pop();
if(visited[t.to])
{
continue;
}
ans += t.dis;
visited[t.to] = true;
for(int j = 0;j < vec[t.to].size();j++) //更新队列
{
Node p = vec[t.to][j];
if(!visited[p.to])
{
q.push(p);
}
}
break;
}
}
printf("%d\n",ans);
for(int i = 1;i <= n;i++)
{
vec[i].clear();
}
while(!q.empty())
{
q.pop();
}
}
int main()
{
int n,m;
int u,v,dis;
cin>>n>>m;
for(int i = 0;i < m;i++)
{
scanf("%d%d%d",&u,&v,&dis);
vec[u].push_back(Node(v,dis));
vec[v].push_back(Node(u,dis));
}
memset(visited,false,sizeof(visited));
int ans = 0;
prime(ans,n);
return 0;
}
相关文章推荐
- Espresso——功能方法介绍
- ngx_cycle_s
- 《统计学习方法》读书笔记——感知机
- 多个AsynceTask无法同时运行的现象分析
- 在iOS 7中使用storyboard(part 1)
- 单元测试覆盖率生成网页报告----(三)
- app运行中点击home后再次点击app图标进入应用时重复登录的方法()
- 【LeetCode从零单排】No15 3Sum
- 多个AsynceTask无法同时运行的现象分析
- 身为一个程序媛的深刻自我检讨
- Xcode SVN "The file can not be opened"
- Django实例--英文、数字与中文之间增加空格
- linux 系统创建软连接
- 观察者模式与事件监听机制
- GitHub 使用教程图文详解
- Delphi静态加载DLL和动态加载DLL示例
- App中显示html网页
- android 获取短信 通讯录 电话记录
- 二分图----最大匹配,最小点覆盖,最大点独立集
- Ajax跨域请求webservice