`

poj Command Network 最小树形图 朱-刘算法模板

    博客分类:
 
阅读更多

连接:http://poj.org/problem?id=3164

Command Network
Time Limit: 1000MS   Memory Limit: 131072K
Total Submissions: 10061   Accepted: 2930

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
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define MAXN 110
#define inf 1000000000
struct Node
{
        double x;
        double y;
}node[MAXN];
int n, m;
bool visited[MAXN], circle[MAXN];
int pre[MAXN];
double graph[MAXN][MAXN];
inline double dist(int i, int j)
{
       return sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x) + (node[i].y - node[j].y)*(node[i].y - node[j].y));
}
inline double min(double a, double b)
{
       if ( a < b)return a;
       return b;
}
void dfs(int u)   //深搜,判断是否存在最小树形图 ,根是否可达每个结点
{
       int i;
       if (visited[u])return;
       visited[u] = true;
       for (i = 1; i <= n; i++)if (!visited[i] && graph[u][i] != inf)dfs(i);
}
bool connect(int root)   //深搜,判断是否存在最小树形图 ,根是否可达每个结点
{
       int i;
       dfs(root);
       for (i = 1; i <= n; i++)if (!visited[i])return false;
       return true;
}
//--------------------------朱刘算法
double zhuliu(int root)
{
       int i, j, k;
       double ans = 0;
       memset(circle,0,sizeof(circle));  //如果某点被删掉,那么circle[i]=1
       while (1)
       {
  //-----------------求出除根点为root外的所有点的入边的最小值
              for (i = 1; i <= n; i++)
              {
                     if(i==root)continue;
                     if (circle[i])continue;
                     graph[i][i] = inf; //把图中所有的自环全都清除,很重要!!!
                     pre[i] = i;  //初始化自己的前一节点是自己
                     for (j = 1; j <= n; j++)  // 求i的入边的最小值
                     {
                            if (circle[j])continue;
                            if (graph[j][i] < graph[pre[i]][i])pre[i] = j;
                     }
              }
  //-------------------遍历找环
              for (i = 1; i <= n; i++)
              {
                     if(i==root)continue;
                     if (circle[i])continue;
                     j = i;
                     memset(visited,false,sizeof(visited));
                     while (!visited[j] && j != root)
                     {
                            visited[j] = true;
                            j = pre[j];
                     }
                     if (j == root)continue;//j==root说明i不在环上
                     i = j;  //找到了环
                     ans += graph[pre[i]][i];
                     for (j = pre[i]; j != i; j = pre[j])
                     {
                            ans += graph[pre[j]][j];
                            circle[j] = 1;   //用环上一点i代表此环,其他点删去,即circle[j]=1
                     }
   //判断环外的每个点A是否与环中的某个点B相连,若是相连的则改变其权值,变为graph<A,B>-graph<pre[B],B>
                     for (j = 1; j <= n; j++)
                     {
                            if (circle[j])continue;
                            if (graph[j][i] != inf)graph[j][i] -= graph[pre[i]][i];    //更新j的入边
                     }

                     for (j = pre[i]; j != i; j = pre[j])  //环上所有点的最优边为人工顶点的边
                     {
                            for (k = 1; k <= n; k++)
                            {
                                   if (circle[k])continue;
                                   if (graph[j][k] != inf)graph[i][k] = min(graph[i][k],graph[j][k]);
                                   if (graph[k][j] != inf)graph[k][i] = min(graph[k][i],graph[k][j] - graph[pre[j]][j]);
                            }
                     }
                     break;
              }
              if (i > n)
              {
                     for (j = 1; j <= n; j++)  //新图树形图的权加环的权
                     {
                            if(j==root)continue;
                            if (circle[j])continue;
                            ans += graph[pre[j]][j];
                     }
                     break;
              }

       }
       return ans;
}

int main()
{
       int i, j, u, v;
//       freopen("in.txt","r",stdin);
       while(scanf("%d %d",&n,&m) != EOF)
       {
              for (i = 1; i <= n; i++)scanf("%lf %lf",&node[i].x,&node[i].y);
              for (i = 1; i <= n; i++)for (j = 1; j <= n; j++)graph[i][j] = inf;
              while (m--)
              {
                     scanf("%d %d",&u,&v);
                     graph[u][v] = dist(u,v);
              }
              memset(visited,false,sizeof(visited));
              int root=1;
              if (!connect(root))printf("poor snoopy\n");
              else printf("%.2lf\n",zhuliu(root));
       }
       return 0;
}

 

 

 

 

 

 

 

 

 

 

 

1
4
分享到:
评论

相关推荐

    Stoer-Wagner算法求全局最小割(模板)

    在POJ2914题中,提供了Stoer-Wagner 算法的实现代码,该代码使用C++语言编写,使用prim算法计算图的最小割,并输出图的全局最小割结果。 Stoer-Wagner 算法是一种常用的算法,用于计算图的全局最小割,该算法可以...

    最小树形图 朱刘算法.docx

    最小树形图问题是一个经典的图论问题,主要目标是在给定的有向带权图中找到一棵以特定顶点(root)为根的有向生成树,使得这棵树的所有边的权重之和最小。朱刘算法,由朱永津和刘振宏在1965年提出,是一种有效解决此...

    北大POJ初级-图算法

    【北大POJ初级-图算法】是一系列针对北京大学在线编程平台POJ(Problem Online Judge)上的初级编程题目,重点在于图论算法的应用。这个解题报告集合了多种图算法的实现,帮助学习者掌握如何在实际问题中运用这些...

    POJ 1751 求最小生成树prim算法(JAVA)

    标题 "POJ 1751 求最小生成树Prim算法(JAVA)" 提到的是一个编程挑战,涉及图论中的经典算法——Prim算法。在计算机科学中,Prim算法是用于寻找加权无向图的最小生成树的一种有效方法。最小生成树是一棵树形结构,...

    北大POJ初级-基本算法

    6. **图论算法**:包括图的遍历(深度优先搜索和广度优先搜索)、最短路径问题(Dijkstra算法、Floyd-Warshall算法)、最小生成树问题(Prim和Kruskal算法)。 7. **字符串处理**:如KMP算法、Rabin-Karp算法、...

    POJ 1789 最小生成树之prim算法

    标题中的“POJ 1789 最小生成树之prim算法”指的是一个在线编程竞赛题目,来源于普林斯顿开放在线课程(POJ)平台。该题目要求参赛者实现Prim算法,这是一种解决图论问题中寻找最小生成树的经典算法。最小生成树是在...

    ACM-POJ 算法训练指南

    2. **最小生成树**:Prim算法和Kruskal算法,用于构建图的最小生成树(poj1789, poj2485, poj1258, poj3026)。 3. **网络流**:Max-flow算法,用于解决最大流问题(poj1094)。 4. **拓扑排序**:解决有向无环图的...

    poj训练计划.doc

    - 最小生成树算法:如Prim算法和Kruskal算法,用于找出图中的最小生成树,如`poj1789, poj2485`。 - 拓扑排序:适用于有向无环图,用于确定任务的执行顺序,如`poj1094`。 - 二分图的最大匹配:如匈牙利算法,...

    POJ2531-Network Saboteur

    【标签】"POJ 2531 Network Saboteur" 提供了问题的关键信息,POJ是一个在线编程竞赛平台,编号2531标识了这个特定的题目,"Network Saboteur"则是题目的名称,可能涉及到网络或图的相关主题。 【压缩包子文件的...

    poj1251 最小生成树

    标题“poj1251 最小生成树”是一个编程竞赛题目,来源于著名的在线编程平台POJ(Programming Online Judge)。这个题目主要涉及图论中的一个经典算法问题——最小生成树(Minimum Spanning Tree, MST)。在图论中,...

    POJ算法题目分类

    图算法是指解决图相关问题的算法,包括图的深度优先遍历和广度优先遍历、最短路径算法、最小生成树算法、拓扑排序、二分图的最大匹配等。 * 图的深度优先遍历和广度优先遍历:图的深度优先遍历和广度优先遍历是指...

    北大POJ中级-基本算法

    【北大POJ中级-基本算法】解题报告与AC代码详解 北京大学的在线编程平台POJ(Problem Set of Peking University)是许多编程爱好者和学习者提升算法技能的重要平台。中级算法题目通常涵盖了一些基础但重要的算法...

    POJ中级图算法所有题目【解题报告+AC代码】

    图算法是计算机科学中的核心部分,它在解决复杂问题时起着至关重要的作用,如网络路由、最短路径、最小生成树、拓扑排序等。在POJ的中级图算法题目中,我们通常会遇到以下几种类型的图问题: 1. **最短路径问题**:...

    POJ 1861 Network

    【标题】"POJ 1861 Network"是一个经典的计算机科学问题,它涉及到图论中的网络连接,并要求我们利用并查集(Disjoint Set)数据结构来检测图中的环路,同时应用快速排序算法来求解最小生成树。这个问题在ACM(国际...

    POJ水题集--50道--增加自信

    POJ水题集-----50道左右-----增加自信啊..

    poj图论题目汇总

    #### 3164 Command Network - 最小树形图 - **知识点**:最小树形图问题,一种特殊的图论问题。 #### 3169 Layout - 差分约束 - **知识点**:差分约束系统。 #### 3177 Redundant Paths - 双联通分量 - **知识...

    最小费用流的原始对偶 (Primal-Dual) 算法.docx

    "最小费用流的原始对偶 (Primal-Dual) 算法" 该算法是融合了直接 ...13. POJ 3422:该题目是一个在线judge平台上的题目,要求使用 zkw 费用流算法来解决最小费用流问题,该题目是 zkw 费用流算法不擅长的一个例子。

    POJ1459-Power Network

    【标签】"POJ 1459 Power Network"表明这是一个关于POJ平台的特定编号题目,涉及的是电力网络相关的问题,可能需要理解图的理论知识和实际应用算法。 【压缩包子文件的文件名称列表】: - "POJ1459-Power Network...

    POJ 分类题目

    最小生成树算法** - **定义**:包括 Prim 算法和 Kruskal 算法。 - **示例题目**: - poj1789 - poj2485 - poj1258 - poj3026 - **应用场景**:适用于构建最小成本网络、电力线路铺设等问题。 **4. 拓扑排序**...

    poj上算法题目分类

    根据提供的信息,我们可以将POJ(Peking Online Judge)平台上的算法题目按照不同的类别进行整理与解析。这对于希望系统性地提高自己算法能力的学习者来说非常有用。下面将基于给出的分类来详细介绍每一类算法的核心...

Global site tag (gtag.js) - Google Analytics