畅通工程

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 27521    Accepted Submission(s): 12062

Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
 
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 

行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
 
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
 
Sample Input
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
 
Sample Output
3
?
//1. 假设有一棵树只包含一个顶点的v的树T。
//2.贪心的选取T和其他顶点之间相连的最小权值的边,并将它加入T中.
//3.不断重复1,2 直到所有的点相连生成一棵最小生成树。
#include<queue>
#include<stack>
#include<math.h>
#include<stdio.h>
#include<numeric>//STL数值算法头文件
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<functional>//模板类头文件
using namespace std; const int INF = 1e9+7;
const int VM = 103;
int G[VM][VM];//存图
void prim(int n)
{
int record[VM];//记录 边的权值
bool vis[VM];//记录是否访问
int ans = 0;
memset(vis, 0, sizeof(vis));//初始化
for (int i = 1; i <= n; i++)
record[i] = G[1][i];//初始化
record[1] = 0;
vis[1] = true;// 1 点标记为已访问
int i;
for (i = 2; i <= n; i++) //进行 n - 1 次操作
{
int u = INF;//初始化
int k;
for (int j = 1; j <= n; j++) //遍历所有顶点
{
if (!vis[j] && u > record[j]) //在所有的未加入的点中 找一个最小的权值
{
k = j;//记录下标
u = record[j];//更新最小值
}
}
if (u == INF)//若图是不连通的
break;//提前退出
vis[k] = true;//标记为已加入
ans += u;//加权值
for (int j = 1; j <= n; j++) //遍历所有的点
{
if (!vis[j] && record[j] > G[k][j])//对未加入的点&&能找到与此点相连且的权值最小的边
record[j] = G[k][j];//进行更新
}
}
//输出
if (i - 1 == n)
printf("%d\n", ans);
else
printf("?\n");
}
int main()
{
int n, m;
while (scanf("%d %d", &n, &m), n) //对边数 和点数的获取
{
for (int i = 1; i <= m; i++) //初始化
{
for (int j = 1; j <= m; j++)
{
G[i][j] = i == j ? 0 : INF;
}
}
while (n--)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);//获取 数据
if (G[u][v] > w)//防止重边&&存两点之间的最短距离
G[u][v] = G[v][u] = w;
}
prim(m);//调用函数
}
return 0;
}




优化

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std; const int INF = 1e9+7;
const int VM = 103; typedef pair<int, int>P;//对组
struct node //前向星 结构体
{
int v, w;
int next;
};
node edge[4 * VM];//前向星数组
int head[VM];//头指针数组
int cnt;//计数
void add(int u, int v, int w) //加边函数
{
edge[cnt].v = v;//顶点
edge[cnt].w = w;//权值
edge[cnt].next = head[u];//下一个
head[u] = cnt++;//头指针
} void prim(int n) //普利姆函数
{
bool vis[VM];//标记是否访问过
int record[VM];//记录权值
int ans = 0;//最小生成树的总值
int count = 0;//计数
priority_queue<P, vector<P>, greater<P> >que;//权值从小到大的队列
fill(record, record + VM, INF);//初始化
memset(vis, 0, sizeof(vis));//初始化
record[1] = 0;//初始化
que.push(P(0, 1));//将 1点 和 record[1] = 0 放入队列
while (!que.empty()) //队列不为空时
{
P p = que.top();//取出队首
que.pop();//删除
int u = p.second;//
if (vis[u] == true)//若此顶点已经加入生成树
continue;//
vis[u] = true;//否则,就标记为加入
ans += record[u];//
count++;//加入点个数
for (int i = head[u]; i != -1; i = edge[i].next) //遍历与该点相邻的点
{
node e = edge[i];
if (record[e.v] > e.w) //更新他们的权值
{
record[e.v] = e.w;//
que.push(P(record[e.v], e.v));//放入队列
}
}
}
//输出
if (count == n)
printf("%d\n", ans);
else
printf("?\n");
}
int main()
{
int n, m; while (scanf("%d %d", &n, &m), n) //边的个数 顶点个数
{
memset(head, -1, sizeof(head));//初始化
cnt = 0;//初始化
while (n--)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);//获取数据
add(u, v, w);//加边
add(v, u, w);//无向图
}
prim(m);//普利姆算法
}
return 0;
}


//克鲁斯卡尔算法用并查集的优化
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int INF = 1e9+7;
const int VM = 103;
struct node //边的结构体
{
int u, v, w;
};
node edge[VM * 2];
int high[VM];//分组的高度
int par[VM];//父节点 bool cmp(const node &a, const node &b)
{
return a.w < b.w;//按w从小到大排序
} int find(int x)
{
if(x!=par[x]) x=find(par[x]);
return par[x];
}
bool same(int x, int y) //判断为否在同一分组中
{
return find(x) == find(y);
}
int unite(int x, int y)
{
x = find(x);//查找根节点
y = find(y);//查找根节点
if(x!=y)
{
par[x]=y;
high[x]++;
}
}
int main()
{
int n, m;
while (scanf("%d %d", &n, &m), n) //获取边的个数 和顶点个数
{
int cnt = 0;//
for (int i = 1; i <= m; i++)//初始化
par[i] = i;
memset(high, 0, sizeof(high));//初始化
while (n--)
{
scanf("%d %d %d", &edge[cnt].u, &edge[cnt].v, &edge[cnt].w);//获取数据
cnt++;
}
sort(edge, edge + cnt, cmp);//按权值从小到大排序
int ans = 0;//最小生成树 权值
int count = 0;//计数
for (int i = 0; i < cnt; i++) //对所有的边
{
node e = edge[i];
if (!same(e.u, e.v)) //若两点不属于一个分组
{
ans += e.w;//权值总和
unite(e.u, e.v);//合并两点
count++;//计数
}
}
//输出
if (count == m - 1)
printf("%d\n", ans);
else
printf("?\n");
}
return 0;
}






最小生成树---->prim算法的应用 hdu1863的更多相关文章

  1. 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。

    //归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...

  2. 最小生成树Prim算法(邻接矩阵和邻接表)

    最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...

  3. 最小生成树—prim算法

    最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...

  4. Highways POJ-1751 最小生成树 Prim算法

    Highways POJ-1751 最小生成树 Prim算法 题意 有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输 ...

  5. SWUST OJ 1075 求最小生成树(Prim算法)

    求最小生成树(Prim算法) 我对提示代码做了简要分析,提示代码大致写了以下几个内容 给了几个基础的工具,邻接表记录图的一个的结构体,记录Prim算法中最近的边的结构体,记录目标边的结构体(始末点,值 ...

  6. 图论算法(五)最小生成树Prim算法

    最小生成树\(Prim\)算法 我们通常求最小生成树有两种常见的算法--\(Prim\)和\(Kruskal\)算法,今天先总结最小生成树概念和比较简单的\(Prim\)算法 Part 1:最小生成树 ...

  7. 最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析

    最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析 最小生成树,老生常谈了,生活中也总会有各种各样的问题,在这里,我来带你一起分析一下这个算法的思路与实现的方式吧~~ 在考研中呢 ...

  8. 最小生成树——prim算法

    prim算法是选取任意一个顶点作为树的一个节点,然后贪心的选取离这棵树最近的点,直到连上所有的点并且不够成环,它的时间复杂度为o(v^2) #include<iostream>#inclu ...

  9. 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

    最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...

随机推荐

  1. 理解 CSS 中的伪元素 :before 和 :after

    CSS 的主要目的是给 HTML 元素添加样式,然而,在一些案例中给文档添加额外的元素是多余的或是不可能的.事实上 CSS 中有一个特性允许我们添加额外元素而不扰乱文档本身,这就是“伪元素”. 你一定 ...

  2. 【总结】前端必须收藏的CSS3动效库!!!

    现在的网站和App的设计中越来越重视用户体验,而优秀的动效则能使你的应用更具交互性,从而吸引更多用户的使用. 如果你对CSS3中定义动效还不熟练,或希望采用更加简单直接的方式在你的应用中引入动效的话, ...

  3. vue-loader 调用了cssLoaders方法配置了css加载器属性。

    module: { loaders: [ // 这里也是相应的配置,test就是匹配文件,loader是加载器, { test: /\.vue$/, loader: 'vue' }, { test: ...

  4. Master of Phi (欧拉函数 + 积性函数的性质 + 狄利克雷卷积)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6265 题目大意:首先T是测试组数,n代表当前这个数的因子的种类,然后接下来的p和q,代表当前这个数的因 ...

  5. python之自然语言处理入门(一)

    前言 NTLK是著名的Python自然语言处理工具包,记录一下学习NTLK的总结. 安装nltk pip install nltk # 测试 import nltk 安装相关的包 import nlt ...

  6. dm368 ipnc3.0环境搭建脚本

    前言 为了方便其他人搭建dm368 ipnc3.0环境,我写了个脚本,执行脚本就可以自动搭建好环境了,绝对的傻瓜操作了,不过有一个地方让我很郁闷,那就是在用sed替换掉某段内容的时候(143行--15 ...

  7. Centos 6.4搭建git服务器【转】

    前阵子公司需要,让我搭个Git服务器,把之前用的SVN上代码迁移到git上去,所以就在阿里云主机上搭了一个,记录了下安装过程,留存文档以备查阅.本篇本章只涉及搭建部分的操作,更多git的使用可以参考文 ...

  8. UVA题解一

    UVA 100 题目描述:经典3n+1问题在\(n \leq 10^6\)已经证明是可行的,现在记\(f[n]\)为从\(n\)开始需要多少步才能到\(1\),给出\(L, R\),问\(f[L], ...

  9. 批量删除.svn文件夹和.svn文件

    新建可运行文件 Windows环境 将下面的代码保存为 kill-svn.bat文件,放到要删除.svn文件的目录下,双击运行即可 @echo on @rem 删除SVN版本控制目录 @rem for ...

  10. ORACLE数据库导出导入数据

    准备工作: 1.登录管理员system 2.create directory dbdata as 'C:\oracle\tempData';--创建备份文件夹 3.grant read,write o ...