poj3164(最小树形图&朱刘算法模板)
题目链接:http://poj.org/problem?id=3164
题意:第一行为n, m,接下来n行为n个点的二维坐标, 再接下来m行每行输入两个数u, v,表点u到点v是单向可达的,求这个有向图的最小生成树即求最小树形图;
思路: 这是一道最小树形图模板题;
我们可以用朱刘算法来解:
朱刘算法只有3步,然后不断循环。
1:找到每个点的最小入边。既然是生成树,那么对于每个点来说,只要选一个权值最小的入边就可以了。
贪心思想。因为如果不是最小入边,那么它肯定不是最小树形图的一条边,考虑它是没有意义的。
2:找环。找环找的是最小入边构成的新图的环。如果没找到环,那么一棵树就已经形成了,
因为树就是没有环的图。再因为边权都是最小的,因此此时最小树形图就已经出来了,停止循环。
3:如果第2步中找到了环,那么这个环就可以缩成一个点。然后构造新图,更新边权。更新边权的方法是:
假设某点u在该环上,并设这个环中指向u的边权是in[u],那么对于每条从u出发的边(u, i, w),在新图中连接(new, i, w)的边,其中new为新加的人工顶点;对于每条进入u的边(i, u, w),在新图中建立边(i, new, w-in[u])的边。之所以是w-in[u]的原因是如果选择了w,那么那个in[u]在树中就是多余的,完全可以删除,所以需要减去,然后再后面的总费用累加中会体现出删掉了这个权值,不理解的画个图就明白了。
代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <iomanip>
#define MAXN 210
using namespace std; const int inf=0x3f3f3f3f;
struct node{
int u, v;
double w; //**u到v的单向距离
}edge[MAXN*]; struct Point{ //**记录每个点的坐标
double x, y;
}point[MAXN]; double in_dist[MAXN]; //记录i点的最短入边距离
int pre[MAXN]; //**记录i节点的前继节点
int id[MAXN]; //**记录新图点节点
int vis[MAXN]; //**判环
int k=; //k为非自环边的数目 double dist(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} void add(int u, int v, double dist){ //***加边
edge[k].u=u;
edge[k].v=v;
edge[k++].w=dist;
} double zhuliu(int root, int n){
double ans=;
while(true){
for(int i=; i<=n; i++){
in_dist[i]=inf;
}
for(int i=; i<k; i++){ //***找点i的最小入边
int u=edge[i].u;
int v=edge[i].v;
double w=edge[i].w;
if(u!=v&&in_dist[v]>w){//**注意这里新图也可能出现自环的情况,若不加u!=v的话会tle
in_dist[v]=w;
pre[v]=u; //**记录v的前继节点
}
}
for(int i=; i<=n; i++){
if(i==root){
continue;
}
ans+=in_dist[i];
if(in_dist[i]>=inf){
return -; //***根节点外还有孤立点,不存在最小树形图
}
}
memset(id, -, sizeof(id));
memset(vis, -, sizeof(vis));
int cnt=;
for(int i=; i<=n; i++){//***枚举每个点,找环
int v=i;
while(v!=root&&vis[v]!=i&&id[v]==-){//**上溯父节点找环
vis[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-){ //***找到了环,缩点并且从新编号
++cnt;
id[v]=cnt;
for(int u=pre[v]; u!=v; u=pre[u]){
id[u]=cnt;
}
}
}
if(!cnt){ //***没有出现环
break;
}
for(int i=; i<=n; i++){//***将余下的不在环中的点也重新编号
if(id[i]==-){
id[i]=++cnt;
}
}
for(int i=; i<k; i++){//***建新图
int u=edge[i].u;
int v=edge[i].v;
edge[i].u=id[u];
edge[i].v=id[v];
if(edge[i].u!=edge[i].v){
edge[i].w-=in_dist[v];
}
}
n=cnt; //**更新节点数目
root=id[root]; //**更新根节点编号
}
return ans;
} int main(void){
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
int u, v, n, m;
while(~scanf("%d%d", &n, &m)){
k=;
for(int i=; i<=n; i++){
scanf("%lf%lf", &point[i].x, &point[i].y);
}
while(m--){
scanf("%d%d", &u, &v);
if(u!=v){ //***删除自环
add(u, v, dist(point[u], point[v]));
}
}
int root=; //**本题中没有指定根节点,任取一个即可
double ans=zhuliu(root, n);
if(ans==-){
puts("poor snoopy");
}else{
printf("%.2f\n", ans); //**poj输出用lf会wa╭(╯^╰)╮
}
}
return ;
}
poj3164(最小树形图&朱刘算法模板)的更多相关文章
- 最小树形图——朱刘算法(Edmonds)
定义:一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 朱刘算法实现过程: [在选出入边集后(看步骤1),若有向图中不存在有向环,说明该图就是最小树形图] 1,选入 ...
- 洛谷P4716 【模板】最小树形图(朱刘算法)
题意 题目链接 Sol 朱刘算法?感觉又是一种神仙贪心算法 大概就是每次贪心的用每个点边权最小的入边更新答案,如果不行的话就缩起来找其他的边 不详细说了,丢链接走人.. #include<bit ...
- POJ 3164 Command Network ( 最小树形图 朱刘算法)
题目链接 Description After a long lasting war on words, a war on arms finally breaks out between littlek ...
- POJ 3164 Command Network 最小树形图 朱刘算法
=============== 分割线之下摘自Sasuke_SCUT的blog============= 最 小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T, ...
- 最小树形图--朱刘算法([JSOI2008]小店购物)
题面 luogu Sol 首先设一个 \(0\) 号点,向所有点连边,表示初始价值 显然这个图的一个 \(0\) 为根的最小有向生成树的边权和就是每个买一次的最小价值 再买就一定能优惠(包含 \(0\ ...
- POJ - 3164-Command Network 最小树形图——朱刘算法
POJ - 3164 题意: 一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 题目就是求这个最小的树形图. 参考资料:https://blog.csdn.net/ ...
- bzoj 4349 最小树形图——朱刘算法
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4349. 学习博客:http://www.cnblogs.com/xzxl/p/7243466 ...
- UVA-11183 Teen Girl Squad (最小树形图、朱刘算法模板)
题目大意:给一张无向图,求出最小树形图. 题目分析:套朱-刘算法模板就行了... 代码如下: # include<iostream> # include<cstdio> # i ...
- POJ--3164--Command Network【朱刘算法】最小树形图
链接:http://poj.org/problem?id=3164 题意:告诉n个点坐标,m条边表示两个点之间有路.从1点開始建立一个有向图最小生成树. 朱刘算法模板题 =============== ...
随机推荐
- Codeforces Round #243 (Div. 1)——Sereja and Two Sequences
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012476429/article/details/24798219 题目链接 题意:给两个长度分别 ...
- (1366, "Incorrect string value: '\\xF3\\xB0\\x84\\xBC</...' for column 'content' at row 1")
插数据库报错 (1366, "Incorrect string value: '\\xF3\\xB0\\x84\\xBC</...' for column 'content' at r ...
- LeetCode:用最少的箭引爆气球【452】
LeetCode:用最少的箭引爆气球[452] 题目描述 在二维空间中有许多球形的气球.对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标.由于它是水平的,所以y坐标并不重要,因此只要知道 ...
- map select reduce
map: 针对每个element进行变换并返回整个修改后的map a.map do |item| a.upcase end a.map(&:upcase) 一样的效果, &:代表了it ...
- <JAVA图像学习笔记>关于Graphics/Graphics2D以及简单的几何图像制作(一个简单钟表的实现)
题外话:正好赶上OperatingSystem的作业要做一个模拟线程/进程调度的问题,决定用JAVA实现才发现这些内容和之前学过的GUI制作是两码事儿- -b 通过学习java.swing库的Acti ...
- 主成分分析(PCA)与SVD奇异值分解
主要参考:https://www.zhihu.com/question/38417101/answer/94338598 http://blog.jobbole.com/88208/ 先说下PCA ...
- 架构设计:系统间通信(34)——被神化的ESB(上)
1.概述 从本篇文章开始,我们将花一到两篇的篇幅介绍ESB(企业服务总线)技术的基本概念,为读者们理清多个和ESB技术有关名词.我们还将在其中为读者阐述什么情况下应该使用ESB技术.接下来,为了加深读 ...
- Keepalived实现心跳检测实现自动重启
项目中服务器如果发生宕机:1.故障转移 2.心跳检测 3.负载均衡 4.自动重启 心跳检测: 心跳检测脚本: 写入nginx_check.sh脚本 vi /etc/keepalived/nginx_ ...
- T58
他们投产的新轿车广获传媒报道.The launch of their new saloon received much media coverage.法律规定禁止近亲结婚.Marriages in p ...
- PowerDesigner根据SQL文件生成PDM数据字典
当PowerDesigner不能直接连接到数据库的时候,可以用到下面这个方法生成数据字典(直接连接数据库生成数据字典在上次随笔中有介绍). 具体操作步骤截图: ↓↓↓这里选择的sql文件是从数据库导出 ...