题目链接

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. pycharm 修改新建文件时的头部模板

    pycharm 修改新建文件时的头部模板 默认为__author__='...' [省略号是默认你的计算机名] 修改这个作者名的步骤: 依次点击:File->Settings->Edito ...

  2. 微信小程序 功能函数 手机号验证*

    // 登录手机验证 loginPhone: function (e) { var phone = e.detail.value; if (!(/^1[34578]\d{9}$/.test(phone) ...

  3. 用SQL查询方式显示GROUP BY中的TOP解决方法[转]

    用SQL查询方式显示GROUP BY中的TOP怎样用一个SQL语句来显示 分组后每个组的前几位 比如把一个学校所有学生的成绩按班级分组,再显示每个班级前五名的信息. 班级     学生   成绩 一班 ...

  4. BZOJ 3143 游走(贪心+期望+高斯消元)

    一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...

  5. DAY4-Flask项目

    项目出现的问题: 问题处在import requests.requests库已经安装了啊; 找了半天也不知道具体错误在哪里,根据提示想是不是http.py这个模块与Python内置的同名模块冲突了?所 ...

  6. Hadoop2.6 安装布置问题总结(单机、分布式)

    在debian7虚拟机上安装hadoop2.6,期间遇到一些问题在此记录一下. 安装参考: Hadoop安装教程_单机/伪分布式配置_Hadoop2.6.0/Ubuntu14.04 Hadoop集群安 ...

  7. HotSpot垃圾收集器GC的种类

      堆内存的结构:

  8. 【hdu2809】 不要62

    http://acm.hdu.edu.cn/showproblem.php?pid=2089 (题目链接) 题意 求区间${[n,m]}$中不含有62和4的数的个数. Solution 数位dp板子. ...

  9. 【hdu4010】 Query on The Trees

    http://acm.hdu.edu.cn/showproblem.php?pid=4010 (题目链接) 题意 link cut tree板子 Solution link cut tree 细节 注 ...

  10. java多线程 -- 同步鎖

    为了解决多线程安全问题在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile .Java 5.0 后增加了一些新的机制,但并不是一种替代内置 ...