题目链接

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. Linux上两种网络连接方式

    模式一:NAT方式好处:路由器更换,或者交换机更换,网络仍然可以使用,所用使用最多 准备工作: 查看VMware服务器启动情况,五个全开模式 vmnet8开启模式 1 配置VMware交换机的ip地址 ...

  2. QtCreator源码分析—2.启动主程序(4篇)

    QtCreator采用插件体系结构.主程序启动插件管理器(PluginManager),再通过插件管理器加载其插件,QtCreator的所有功能均使用插件实现. 我们先来分析主程序对插件管理器的主要操 ...

  3. Java override 和 overload 的区别和联系

    方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现.重写(Overriding)是父类与子类之间多态性的一种表现,而重载(Overloading)是一个类中多 ...

  4. linux下安装java jdk

    第一步:查看java对应版本               yum search java 我自己装的是1.8版本的java包 第二步:装java包 yum install java-1.8.0-ope ...

  5. BZOJ5123 线段树的匹配(树形dp)

    线段树的任意一棵子树都相当于节点数与该子树相同的线段树.于是假装在树形dp即可,记忆化搜索实现,有效状态数是logn级别的. #include<iostream> #include< ...

  6. BZOJ3309 DZY Loves Math(莫比乌斯反演+线性筛)

    一通正常的莫比乌斯反演后,我们只需要求出g(n)=Σf(d)*μ(n/d)的前缀和就好了. 考虑怎么求g(n).当然是打表啊.设n=∏piai,n/d=∏pibi .显然若存在bi>1则这个d没 ...

  7. java并发编程中CountDownLatch和CyclicBarrier的使用

    在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景,遇到这样的场景应该如何解决? 如果是一个线程等待一个线程,则可以通过await()和notify()来实现: 如果是一个线程等待多个线程 ...

  8. 【省选水题集Day1】一起来AK水题吧! 题目(更新到B)

    题解:http://www.cnblogs.com/ljc20020730/p/6937954.html 水题A: [AHOI2001]质数和分解 题目网址: https://www.luogu.or ...

  9. 【Learning】容斥原理

    PPT在这里 https://files.cnblogs.com/files/RogerDTZ/%E5%AE%B9%E6%96%A5%E5%8E%9F%E7%90%86.pdf

  10. 洛谷 P2598 [ZJOI2009]狼和羊的故事 解题报告

    P2598 [ZJOI2009]狼和羊的故事 题目描述 "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" \(Orez\)听到这首歌, ...