题目链接

Description

After a long lasting war on words, a war on arms finally breaks out between littleken’s and KnuthOcean’s kingdoms. A sudden and violent assault by KnuthOcean’s force has rendered a total failure of littleken’s command network. A provisional network must be built immediately. littleken orders snoopy to take charge of the project.

With the situation studied to every detail, snoopy believes that the most urgent point is to enable littenken’s commands to reach every disconnected node in the destroyed network and decides on a plan to build a unidirectional communication network. The nodes are distributed on a plane. If littleken’s commands are to be able to be delivered directly from a node A to another node B, a wire will have to be built along the straight line segment connecting the two nodes. Since it’s in wartime, not between all pairs of nodes can wires be built. snoopy wants the plan to require the shortest total length of wires so that the construction can be done very soon.

Input

The input contains several test cases. Each test case starts with a line containing two integer N (N ≤ 100), the number of nodes in the destroyed network, and M (M ≤ 104), the number of pairs of nodes between which a wire can be built. The next N lines each contain an ordered pair xi and yi, giving the Cartesian coordinates of the nodes. Then follow M lines each containing two integers i and j between 1 and N (inclusive) meaning a wire can be built between node i and node j for unidirectional command delivery from the former to the latter. littleken’s headquarter is always located at node 1. Process to end of file.

Output

For each test case, output exactly one line containing the shortest total length of wires to two digits past the decimal point. In the cases that such a network does not exist, just output ‘poor snoopy’.

Sample Input

4 6

0 6

4 6

0 0

7 20

1 2

1 3

2 3

3 4

3 1

3 2

4 3

0 0

1 0

0 1

1 2

1 3

4 1

2 3

Sample Output

31.19

poor snoopy

分析:

题意:两国交战,一个国家的指挥官要将命令通过传输网络下达到部队,部队通过架设电缆来传输信息。电缆传输信息是单向的,并且命令只要能够传下去就可以,不需要下面的不对向上级汇报。现在给出各个部队的位置和可以建立连接的部队,问至少需要多长的电缆。

理解题目意思后,就转换为给你一个有向图,求有向图的最小树形图。在这里要用到朱刘算法(终于见到我们中国人自己写出的算法了)。具体步骤如下:

基于贪心和缩点的思想。

假设根的顶点是V0。

(1)除了根结点外,所有的点Vi,找到以Vi为终点的最短的边,加入集合中(pre[v]存放的是终点v的起点,In[v]存放终点为v的最短的边)

(2)检查集合中有没有有向环和收缩点。若没有有向环和收缩点,结束计算;若没有有向环、但含收缩边,则跳至步骤(4);若含有有向环,则跳至步骤(3)。

(3)含有有向环,则收缩有向环(缩点),把有向环收缩为一个点,其有向环内的边被收缩掉,而环外的边被保留,构建新图,重复步骤(1)、(2)。

(4)没有有向环,有收缩边,则展开收缩边。

具体的可以根据图来理解一下

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<limits.h>
using namespace std;
const int MAXN = 110;
const int MAXM = 10010;
const int INF=0x3f3f3f3f;
//存储边的信息
struct Node
{
int from;
int to;
double w;
}Edges[MAXM]; //存储点的信息
struct Node1
{
double x;
double y;
}Point[MAXN]; //计算两点间的距离,也就是在计算边长
double Dist(Node1 a, Node1 b)
{
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x+y*y);
} //pre是i点的起点,
int pre[MAXN],vis[MAXN],flag[MAXN];
double In[MAXN],sum;//IN是在表示以i为终点的最短边长 double ZhuLiu(int root,int N,int M)
{
sum = 0;
while(true)
{
for(int i = 0; i < N; ++i)
In[i] = INF; for(int i = 0; i < M; ++i)//找到以没个遍为终点的最短边
{
int u = Edges[i].from;//起点
int v = Edges[i].to;//终点
if(Edges[i].w < In[v] && u != v)
{
pre[v] = u;//v为终点,pre[v]存放起点
In[v] = Edges[i].w;//权值最小的边
}
} for(int i = 0; i < N; ++i)//如果存在除root以外的孤立点,则不存在最小树形图
{
if(i == root)
continue;
if(In[i] == INF)
return -1;
} int CntNode = 0;
memset(flag,-1,sizeof(flag));//flag是重新的编号
memset(vis,-1,sizeof(vis));//vis是标记他们在那个环里面
In[root] = 0;
for(int i = 0; i < N; ++i) //找环,标记每个环
{
sum += In[i];
int v = i;
while(vis[v]!=i && flag[v]==-1 && v!=root)//每个点寻找其前序点,要么最终寻找至根部,要么找到一个环
{
vis[v] = i;
v = pre[v];
}
//找到了一个环
if(v != root && flag[v] == -1) //新图重新编号
{
for(int u = pre[v]; u != v; u = pre[u])
flag[u] = CntNode;
flag[v] = CntNode++;//还是自身的编号,只是在编号的同时实现了编号数目的增加
}
}
if(CntNode == 0) //无环,跳出
break;
for(int i = 0; i < N; ++i)//给那些没有形成环的点也要重新编号
{
if(flag[i] == -1)
flag[i] = CntNode++;
}
for(int i = 0; i < M; ++i) //建立新图,更新其他点到环的距离
{
int v = Edges[i].to;
Edges[i].from = flag[Edges[i].from];
Edges[i].to = flag[Edges[i].to];
if(Edges[i].from != Edges[i].to)
Edges[i].w -= In[v];
}
N = CntNode;
root = flag[root];
}
return sum;
} int main()
{
int x,y,N,M;
while(~scanf("%d%d",&N,&M))
{
int id = 0;
for(int i = 0; i < N; ++i)
scanf("%lf%lf",&Point[i].x,&Point[i].y);
for(int i = 0; i < M; ++i)
{
scanf("%d%d",&x,&y);
if(x == y)
continue;
x--;
y--;
Edges[id].from = x;
Edges[id].to = y;
Edges[id++].w = Dist(Point[x],Point[y]);
}
double ans = ZhuLiu(0,N,id);
if(ans == -1)
printf("poor snoopy\n");
else
printf("%.2lf\n",ans);
}
return 0;
}

POJ 3164 Command Network ( 最小树形图 朱刘算法)的更多相关文章

  1. POJ 3164 Command Network 最小树形图 朱刘算法

    =============== 分割线之下摘自Sasuke_SCUT的blog============= 最 小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T, ...

  2. POJ 3164 Command Network 最小树形图

    题目链接: 题目 Command Network Time Limit: 1000MS Memory Limit: 131072K 问题描述 After a long lasting war on w ...

  3. POJ - 3164-Command Network 最小树形图——朱刘算法

    POJ - 3164 题意: 一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 题目就是求这个最小的树形图. 参考资料:https://blog.csdn.net/ ...

  4. POJ 3164 Command Network 最小树形图模板

    最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...

  5. 最小树形图——朱刘算法(Edmonds)

    定义:一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 朱刘算法实现过程: [在选出入边集后(看步骤1),若有向图中不存在有向环,说明该图就是最小树形图] 1,选入 ...

  6. poj3164(最小树形图&朱刘算法模板)

    题目链接:http://poj.org/problem?id=3164 题意:第一行为n, m,接下来n行为n个点的二维坐标, 再接下来m行每行输入两个数u, v,表点u到点v是单向可达的,求这个有向 ...

  7. 最小树形图--朱刘算法([JSOI2008]小店购物)

    题面 luogu Sol 首先设一个 \(0\) 号点,向所有点连边,表示初始价值 显然这个图的一个 \(0\) 为根的最小有向生成树的边权和就是每个买一次的最小价值 再买就一定能优惠(包含 \(0\ ...

  8. 洛谷P4716 【模板】最小树形图(朱刘算法)

    题意 题目链接 Sol 朱刘算法?感觉又是一种神仙贪心算法 大概就是每次贪心的用每个点边权最小的入边更新答案,如果不行的话就缩起来找其他的边 不详细说了,丢链接走人.. #include<bit ...

  9. bzoj 4349 最小树形图——朱刘算法

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4349. 学习博客:http://www.cnblogs.com/xzxl/p/7243466 ...

随机推荐

  1. 爬虫学习之-scrapy交互式命令

    scrapy shell https:///www.baidu.com  会启动爬虫请求网页 view(response) 会在浏览器打开请求到的临时文件 response.xpath("/ ...

  2. Linux内核0.11 setup文件说明

    一.总体功能介绍 这是关于Linux-kernel-0.11中boot文件夹下setup.s源文件的实现功能的总结说明. setup.s是一个操作系统加载程序,它的主要功能是利用BIOS中断读取机器系 ...

  3. Powershell笔记之MVA课程

    很早之前看过MVA的Powershell课程,最近准备回顾一下,还是有一些意外的收获. <<快速入门 : PowerShell 3.0 高级工具和脚本>> 1. Invoke- ...

  4. TCP&UDP基础

    TCP TCP/IP是一种网络通讯协议,而socket则是TCP/IP网络最为通用的API,即一种应用程序接口,称为套接字.TCP是面向连接的协议,在进行数据收发前必须连接,且在收发时必须保持该连接. ...

  5. Android ComponentName的用法

    ComponentName(组件名称)是用来打开其他应用程序中的Activity或服务的. 用法: Intent it=new Intent(); it.setComponent(new Compon ...

  6. QQ分享-定制分享卡片

    一般H5页面在进行分享的时候,都会生成一个分享卡片,但是这些卡片的生成是很多时候是我们是想要生成的卡片, 对于QQ,我们只需要在html页面里加如3个标签即可,如下: <meta itempro ...

  7. 遇到问题----java----myeclipse或者eclipse发布的项目时配置文件不更新或者无配置文件

    myeclipse或者eclipse发布的项目时配置文件不更新或者无配置文件. 正常的web项目有目录 src/main/resources 和 src/main/java 这两个目录默认在编译发布时 ...

  8. WinForm查询大数据界面假死,使用异步调用解决

    用DataGridView无分页绑定一个几千条数据的查询,查询的时候界面直接卡死十几秒,用户体验非常不好,因此用异步操作解决界面卡死的问题原本场景:点击[查询]后,界面直接卡死优化场景:点击[查询]后 ...

  9. scala 的安装 与 IDEA安装使用

    一.安装 scala 1.下载scala-2.11.8.msi 安装包,   首先去官网http://www.scala-lang.org/,然后点击导航栏的DOWNLOAD,进入下载链接:http: ...

  10. 【线段树】【P4198】 楼房重建

    Description 小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没 ...