题意简单:去掉最小生成树的某一条边并补上一条,求MaxVal

思路:贪心(借鉴Yamidie的思路。。。)

分别求出最小生成树和次最小生成树,再在这两棵树上求最小生成树

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn = ;
const int maxm = maxn*maxn;
const int inf1 = 0x3f3f3f3f;
const double inf2 = ; struct Point {
double x,y;
}pnt[ maxn ];
struct Edge{
int u,v;
double val;
int id;
}edge[ maxn<< ];
int cnt_edge;
double mat[ maxn ][ maxn ];
double dis[ maxn ];
bool vis[ maxn ];
int pre[ maxn ]; double LenPrim1;
double LenPrim2; int fa[ maxn ],rank[ maxn ]; int find( int x ){
if( x==fa[x] ) return x;
else return fa[ x ] = find( fa[x] );
} void init( int n ){
for( int i=;i<n;i++ ){
fa[ i ] = i;
rank[ i ] = ;
}
return ;
} double dist( int i,int j ){
return sqrt( (pnt[i].x-pnt[j].x)*(pnt[i].x-pnt[j].x)+(pnt[i].y-pnt[j].y)*(pnt[i].y-pnt[j].y) );
} int cmp( Edge a,Edge b ){
return a.val<b.val;
} void GetMap( int n ){
for( int i=;i<n;i++ )
for( int j=;j<n;j++ ){
mat[i][j] = dist( i,j );
//printf("mat[%d][%d]=%.3lf\n",i,j,mat[i][j]);
}
return ;
} double prim( int n,int Belong ){
for( int i=;i<n;i++ ){
dis[ i ] = mat[][i];
vis[ i ] = false;
pre[ i ] = ;
}
vis[] = true;
//if( Belong==2 ){
// for( int i=0;i<n;i++ )for( int j=0;j<n;j++ )
//printf("mat[%d][%d]=%.3lf\n",i,j,mat[i][j]);
//}
double ans = ;
for( int i=;i<n;i++ ){
int id = -;
double M = inf2;
for( int j=;j<n;j++ ){
if( !vis[j] && M>dis[j] ){
M = dis[j];
id = j;
}
}
if( id==- ) break;
vis[ id ] = true;
ans += M;
edge[ cnt_edge ].u = pre[ id ];
edge[ cnt_edge ].v = id;
edge[ cnt_edge ].id = Belong;
edge[ cnt_edge ].val = mat[ id ][ pre[id] ];
//printf("u = %d,v = %d\n",edge[cnt_edge].u,edge[cnt_edge].v);
cnt_edge ++ ;
for( int j=;j<n;j++ ){
if( !vis[j] && dis[j]>mat[id][j] ){
dis[j] = mat[id][j];
pre[ j ] = id;
}
}
}
return ans;
} void Deal( int n ){
for( int i=;i<cnt_edge;i++ ){
mat[ edge[i].u ][ edge[i].v ] = inf2;
mat[ edge[i].v ][ edge[i].u ] = inf2;
}
} double Kruskal( int n,int id ){
double ans = ;
init( n );
int cnt = ;
for( int i=;i<cnt_edge;i++ ){
if( i==id ) continue;
int fx = find( edge[i].u );
int fy = find( edge[i].v );
if( fx!=fy ){
if( rank[ fx ]<rank[ fy ] ){
rank[ fy ] += rank[ fx ];
fa[ fx ] = fy;
}
else {
rank[ fx ] += rank[ fy ];
fa[ fy ] = fx;
}
cnt ++ ;
ans += edge[i].val;
if( cnt==n- ) break;
}
}
return ans;
} int main(){
int T;
scanf("%d",&T);
while( T-- ){
int n;
double k;
scanf("%d%lf",&n,&k);
for( int i=;i<n;i++ )
scanf("%lf%lf",&pnt[i].x,&pnt[i].y);
GetMap( n );
cnt_edge = ;
LenPrim1 = prim( n, );
Deal( n );
LenPrim2 = prim( n, );
double ans = LenPrim1;
double temp_ans = ;
sort( edge,edge+cnt_edge,cmp );
//printf("cnt_edge = %d\n",cnt_edge);
for( int i=;i<cnt_edge;i++ ){
if( edge[i].id== && edge[i].u!= && edge[i].v!= ){
temp_ans = Kruskal( n,i );
if( temp_ans>ans )
ans = temp_ans;
}
}
printf("%.2lf\n",ans*k);
}
return ;
}

HDU4756+Prim的更多相关文章

  1. hdu4126_hdu4756_求最小生成树的最佳替换边_Kruskal and Prim

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:  Portal: hdu4126 hdu4756  原题目 ...

  2. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  3. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  4. 最小生成树(prim&kruskal)

    最近都是图,为了防止几次记不住,先把自己理解的写下来,有问题继续改.先把算法过程记下来: prime算法:                  原始的加权连通图——————D被选作起点,选与之相连的权值 ...

  5. Prim 最小生成树算法

    Prim 算法是一种解决最小生成树问题(Minimum Spanning Tree)的算法.和 Kruskal 算法类似,Prim 算法的设计也是基于贪心算法(Greedy algorithm). P ...

  6. poj1789--最小生成树(prim)

    水题... 题目大意: 用一个7位的字符串代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数.一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance ...

  7. 最小生成树のprim算法

    Problem A Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Sub ...

  8. poj2485 kruskal与prim

    Kruskal: #include<iostream> #include<cstdio> #include<algorithm> using namespace s ...

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

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

随机推荐

  1. android 获取前台进程

    String getTopActivity() { ActivityManager manager = (ActivityManager)getSystemService(ACTIVITY_SERVI ...

  2. Cocos移植到Android-使用Eclipse交叉编译打包

    如果对命令行望而生畏,我们可以借助于安装有ADT插件的Eclipse工具实现交叉编译.使用Eclipse进行交叉编译,首先需要将要编译的工程导入到Eclipse的Workspace中,Workspac ...

  3. Foundation与Core Foundation内存管理基本原则简述

    内存管理是一个十分重要的事情,稍有不慎就会发生内存泄漏或者是野指针的错误.内存泄漏一般表示没有任何指针指向的内存区域,由于这块内存在对象图中无法查找到,所以有可能永远都无法回收,如果内存泄漏的空间比较 ...

  4. 控制GridView中字段的长度,规范数据

    前台:   <asp:GridView ID="GridView1" runat="server" OnRowDataBound="GridVi ...

  5. 浅谈css中的position属性

    我觉得吧,css如果不考虑浏览器的兼容问题的话,最让人头疼的应该就是position了,反正我是这么觉得的,为了能基本上搞清楚position的几种情况,我找了一些资料,做了一个小实验,下面是实验的过 ...

  6. 学习C++ Primer 的个人理解(一)

    <C++ Primer>这本书可以说是公认的学习C++最好的书,但我觉得不是特别适合作为教材,书中内容的顺序让人有些蛋疼.我个人认为初学此书是不能跳着看的.如果急于上手的话,我更推荐< ...

  7. 集成产品开发-IPD简介

    内训IPD流程,听完后,觉的流程的力量很强大,可以高效的团队几千上万人的研发团队,来正确地为同一个目标前进.因为讲解者是从华为出来的,所以,相关的案例分析以及理解,都是以华为研发为模板来讲解的.这没错 ...

  8. HTML5之 Microdata微数据

    - 为何需要微数据 长篇加累版牍,不好理解 微标记来标注其中内容,让其容易识辨 - RDFa Resource Description Framework http://www.w3.org/TR/m ...

  9. 谷歌浏览器支持小于12px的字体

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  10. Linq一对多联合查询

    问题: 学生表,班级表,我要班级下面学生 A表,字段:AID,CLASSB表,字段 :BID,BNAME,AIDA表数据1 班级12 班级2B表数据1 学生1 12 学生2 1 3 学生3 24 学生 ...