hdoj 1875 畅通工程再续 (最小生成树之prim算法)
来源:互联网 发布:买彩软件 编辑:程序博客网 时间:2024/04/28 19:25
最小生成树
n使用不同的遍历图的方法,可以得到不同的生成树;从不同的顶点出发,也可能得到不同的生成树。
n按照生成树的定义,n个顶点的连通网络的生成树有 n个顶点、n-1条边。
n构造最小生成树的准则
n必须使用且仅使用该网络中的n-1条边来联结网络中的 n个顶点;
n不能使用产生回路的边;
n各边上的权值的总和达到最小。
prim算法
普里姆算法的基本思想:
从连通网络 N = { V, E }中的某一顶点 u0 出发,选择与它关联的具有最小权值的边( u0, v ),将其顶点加入到生成树顶点集合U中。
以后每一步从一个顶点在 U中,而另一个顶点不在 U 中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合 U中。如此继续下去,直到网络中的所有顶点都加入到生成树顶点集合 U中为止。
采用邻接矩阵作为图的存储表示
分析以上算法,设连通网络有 n个顶点, 则该算法的时间复杂度为 O(n2), 它适用于边稠密的网络。
注意:当各边有相同权值时,由于选择的随意性,产生的生成树可能不唯一。当各边的权值不相同时,产生的生成树是唯一的。
下面是杭电的一道例题 hdoj1875
畅通工程再续
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 20017 Accepted Submission(s): 6281
Problem Description
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
Output
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
Sample Input
2210 1020 2031 12 21000 1000
Sample Output
1414.2oh!
克鲁斯卡尔算法(已ac)
<span style="font-size:14px;">#include<cstdio>#include<algorithm>#include<math.h>using namespace std;int per[103];void init(){for(int i=0;i<=102;i++) //由于上边定义的是103数组,此时只能访问0~102;不能用103这个位置,否则越界 per[i]=i;}struct node{int x;int y;}dao[103];struct node2{int a;int b;double changdu; }p[103*103];double cmp(node2 a,node2 b){return a.changdu<b.changdu;}int find(int x){if(x==per[x])return x;elsereturn per[x]=find(per[x]);}int join(int x,int y){int fx=find(x);int fy=find(y);if(fx!=fy){per[fy]=fx;return 1;}elsereturn 0;}int main(){int n,m,i,j;scanf("%d",&n);while(n--){int x=0;scanf("%d",&m);init(); //初始化,容易丢 for(i=0;i<m;i++) scanf("%d%d",&dao[i].x,&dao[i].y); //这也可以定义成两个 数组来存储 for(i=0;i<m;i++){ for(j=i+1;j<m;j++){double f=(double)(dao[j].x-dao[i].x)*(dao[j].x-dao[i].x)+(double)(dao[j].y-dao[i].y)*(dao[j].y-dao[i].y);p[x].changdu=sqrt(f); //注意前一句的强制转化,也可以不写double,写成1.0*后边的等式 p[x].a=i;p[x].b=j;x++;}}sort(p,p+x,cmp);double sum=0;int cnt=1;for(i=0;i<x;i++){if(join(p[i].a,p[i].b)&&p[i].changdu>=10&&p[i].changdu<=1000){sum=sum+p[i].changdu;cnt++;}} if(cnt>=m)printf("%.1lf\n",sum*100); //double输出用lf elseprintf("oh!\n") ; }return 0;}</span>
1、建立编号。(找到两个点之间的联系,然后编号成第几组)
2、按照最小代价排序(一般为结构体排序)
3、利用并查集,边连接,边判断,排除成环的情况,并记录连接点的个数。
4、判段连接点个数是否等于所需连接物体数量。
prim算法(ac)
#include<stdio.h>#include<string.h>#include<math.h>#define max 1000#define INF 0xfffffffint n;int x[110],y[110];double g[110][110]; double dis(int a,int b){return sqrt(1.0*(x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));}void prim(){double dis[110],min,sum;int vis[110];int v,i,j,k;memset(vis,0,sizeof(vis)); //此数组为1时,代表进入集合,否则没进入集合 for(i=1;i<=n;i++)dis[i]=g[1][i]; //记录i点到集合1的距离 vis[1]=1; //让第一个点进入集合 for(v=1;v<n;v++) { min=INF;// k=1; //可以不初始化,因为每次k都是集合外的点距离集合 内点的最近距离坐标,自动更新 for(i=1;i<=n;i++) if(!vis[i]&&dis[i]<min) { min=dis[i]; //把距离1的最近距离赋给了min k=i;//把点的坐标赋给了k } if(min==INF) //说明外面的点要想进来,距离都不符合题意 { printf("oh!\n"); return ; } vis[k]=1; for(i=1;i<=n;i++) if(!vis[i]&&dis[i]>g[k][i]) dis[i]=g[k][i]; //注意dis记录的是集合内部距离集合外每一个点的最小距离,不是某个点 } sum=0; for(i=2;i<=n;i++) sum+=dis[i]*100.0; printf("%.1lf\n",sum) ; return ; }int main(){int i,j,m;scanf("%d",&m);while(m--){scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);for(i=1;i<=n;i++)for(j=1;j<=n;j++){g[i][j]=dis(i,j); //记录i点到j点的距离 if(g[i][j]<10||g[i][j]>1000)g[i][j]=INF; //把不符合题意的点直接赋值无穷大,相当于做标记,便于输出 }prim();}return 0;}
0 0
- hdoj 1875 畅通工程再续 (最小生成树之prim算法)
- hdoj 1875 畅通工程再续 ( 最小生成树--prim )
- hdoj 1875 畅通工程再续 【最小生成树】【prim算法】
- HDOJ 1863:畅通工程 Prim算法求解最小生成树
- Prim算法-最小生成树(附题:HDU-1875 畅通工程再续)
- HDOJ 1875 畅通工程再续 最小生成树 kruskal && prim
- hdoj 1875 畅通工程再续【最小生成树 kruskal && prim】
- hdoj-1875 畅通工程再续【最小生成树--prim&&kruskal】
- HDOJ畅通工程之并查集and最小生成树prim算法
- HDOJ 1879 继续畅通工程 (Prim 最小生成树)
- HDOJ 1875 畅通工程再续(最小生成树)
- hdoj 1875 畅通工程再续(最小生成树)
- hdu1875 畅通工程再续 (最小生成树之prim 算法)
- hdu1879 继续畅通工程 (最小生成树之prim 算法)
- hdu 1875 畅通工程再续(最小生成树Prim)
- hdu 1875畅通工程再续-prim最小生成树
- hdu 1875 畅通工程再续 最小生成树prim
- HDU 1875 畅通工程再续 Prim最小生成树
- 读书笔记-APUE第三版-(10)信号
- 在 Visual C++ 中以错误的顺序链接 CRT 库和 MFC 库时出现 LNK2005 错误
- hdu 2120 Ice_cream's world I (简单并查集 + 判环)
- java邮件发送和短信发送(一)
- Linux下usb转串口工具minicom安装
- hdoj 1875 畅通工程再续 (最小生成树之prim算法)
- Kaldi学习笔记:跑tidigits样例
- SAS SATA SSD IDE硬盘介绍区别
- java web-上传文件到tomcat服务器上路径问题
- 最小割问题
- 三个实例演示 Java Thread Dump 日志分析
- CSUOJ:K swap operation
- IIS服务器下discuz论坛网站搭建与主页跳转错误(当不加forum.php时候报错)
- hdu 5375 Gray code dp