POJ 3164 Command Network(最小树形图模板题+详解)

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

题意:

求最小树形图。

思路:

套模板。

引用一下来自大神博客的讲解:http://www.cnblogs.com/acjiumeng/p/7136604.html

算法步骤如下:

1.判断图的连通性,若不连通直接无解,否则一定有解。

2.为除了根节点以外的所有点选择一个权值最小的入边,假设用pre数组记录前驱,f数组记录选择的边长,记所选边权和为temp。

3.(可利用并查集)判断选择的的边是否构成环,若没有则直接$ans+=temp$并输出ans,若有,则进行下一步操作。

4.对该环实施缩点操作,设该环上有点$V1,V2……Vi……Vn$,缩成的点为node ,对于所有不在环中的点P进行如下更改:

(1) 点P到node的距离为min{$a[p,Vi]-f[Vi]$} (a为边集数组)

(2)点node到p的距离为min{$a[Vi,p]$}

操作(1)的理解:先假设环上所有边均选上,若下次选择某一条边进入该环,则可以断开进入点与进入点的前驱之间的边,即断开F[进入点],所以等效为直接把$a[p,node]$赋值为min{$a[p,Vi]-f[Vi]$}。

特别提醒:本题有自环,可以提前删掉,因为它没有用。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<set>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef pair<int,ll> pll;
 15 const int inf = 0x3f3f3f3f;
 16 const int maxn=1000+5;
 17 const int mod=1e9+7;
 18
 19 int n, m;
 20
 21 struct point
 22 {
 23     double x,y;
 24 }p[maxn];
 25
 26 struct node
 27 {
 28     int u,v;
 29     double w;
 30 }edge[maxn*maxn];
 31
 32 int pre[maxn],id[maxn],use[maxn];
 33 double in[maxn];
 34
 35 double dis(point a,point b)
 36 {
 37     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 38 }
 39
 40 double mini_tree(int root,int n,int m)//分别是树根,节点数,边数,序号从1开始
 41 {
 42     double ans=0;
 43     int u;
 44     while(true)
 45     {
 46         for(int i=1;i<=n;i++)  in[i]=inf;
 47         for(int i=1;i<=m;i++)
 48         {
 49             int u=edge[i].u;
 50             int v=edge[i].v;
 51             if(edge[i].w<in[v]&&u!=v)
 52             {
 53                 in[v]=edge[i].w;
 54                 pre[v]=u;
 55             }
 56         }//找最小的入边
 57         for(int i=1;i<=n;i++)
 58         {
 59             if(i==root)continue;
 60             ans+=in[i];//把边权加起来
 61             if(in[i]==inf)//如果存在没有入弧的点则不存在最小树形图
 62                 return -1;
 63         }
 64         memset(id,-1,sizeof(id));
 65         memset(use,-1,sizeof(use));
 66         int cnt=0;
 67         for(int i=1;i<=n;i++)//枚举每个点,搜索找环
 68         {
 69             int v=i;
 70             while(v!=root&&use[v]!=i&&id[v]==-1)
 71             {
 72                 use[v]=i;
 73                 v=pre[v];
 74             }
 75             if(v!=root&&id[v]==-1)//当找到环的时候缩点编号
 76             {
 77                 ++cnt;
 78                 id[v]=cnt;
 79                 for(u=pre[v];u!=v;u=pre[u])
 80                     id[u]=cnt;
 81             }
 82         }
 83         if(cnt==0)//如果没有环结束程序
 84             break;
 85         for(int i=1;i<=n;i++)//把余下的不在环里的点编号
 86             if(id[i]==-1)
 87                 id[i]=++cnt;
 88         for(int i=1;i<=m;i++)//建立新的图
 89         {
 90             int u=edge[i].u;
 91             int v=edge[i].v;
 92             edge[i].u=id[u];
 93             edge[i].v=id[v];
 94             if(edge[i].u!=edge[i].v)
 95                 edge[i].w-=in[v];
 96         }
 97         n=cnt;//更新节点数和根节点的编号
 98         root=id[root];
 99     }
100     return ans;
101 }
102
103 int main()
104 {
105     //freopen("in.txt","r",stdin);
106     while(~scanf("%d%d",&n,&m))
107     {
108         for(int i=1;i<=n;i++)  scanf("%lf%lf",&p[i].x,&p[i].y);
109         for(int i=1;i<=m;i++)
110         {
111             scanf("%d%d",&edge[i].u,&edge[i].v);
112             if(edge[i].u!=edge[i].v)
113                 edge[i].w=dis(p[edge[i].u],p[edge[i].v]);
114             else edge[i].w=inf;
115         }
116         double ans=mini_tree(1,n,m);
117         if(ans==-1)  printf("poor snoopy\n");
118         else printf("%.2f\n",ans);
119     }
120     return 0;
121 }
时间: 2024-10-11 23:22:34

POJ 3164 Command Network(最小树形图模板题+详解)的相关文章

POJ 3164 Command Network 最小树形图-朱刘算法裸题

题目来源:POJ 3164 Command Network 题意:求以1为根的最小树形图 没有输出字符串 思路:直接高朱刘算法 不懂的可以百度 学会了就是直接套模板的事情 其实就是不断消圈而已 不构成圈就有解 无法从根到达其他点就无解 #include <cstdio> #include <cstring> #include <cmath> const int maxn = 110; const int maxm = 50010; const double INF =

POJ 3164 Command Network (最小树形图-朱刘算法)

题目地址:POJ 3164 最小树形图第一发. 把一个v写成u了.....TLE了一晚上...(虽说今晚出去玩了..) 刚开始看这个算法的时看模板以为又是一个isap....吓得一个哆嗦.但是仔细看了看之后发现还是挺好理解的.写下自己的理解. 朱刘算法其实只有3步,然后不断循环. 1:找到每个点的最小入边.既然是生成树,那么对于每个点来说,只要选一个权值最小的入边就可以了.贪心思想.因为如果不是最小入边,那么它肯定不是最小树形图的一条边,考虑它是没有意义的. 2:找环.找环找的是最小入边构成的新

POJ 3164 Command Network(最小树形图)

Command Network Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 13817   Accepted: 3973 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 a

【POJ3164】Command Network 最小树形图模板题 重修版

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44935891"); } 我以前的版本 算法构造过程以及傻叉代码+弱版注释见以前博客 http://blog.csdn.net/vmurder/article/details/38819711 最小树形图: 名词解释: 其实就是有向图

最小树形图 【poj 3164 Command Network】

定义:在有向图上的最小生成树. 算法过程:和最小生成树一样,不过这个不是无向图的,但是也可以用类似的算法,最小树形图的第一个算法数朱刘算法,依据最小生成树数算法形成的. 我们知道,在最小生成树算法中,我们每次选长度最短的边,如果满足条件则加入最小生成树中,知道所有的点都在树中,最小树形图同样. 首先和最小生成树一样,首先必须保证图联通,否则不能形成最小树形图. 但是由于是有向的,而我们只要找所有点的入边中最小的入边的和就是这个图的最小树形图,但是最关键的地方在于可能形成环,我们要做的就是缩点,把

poj Command Network 最小树形图

规定根节点,求一颗生成树使得权值最小,但由于是有向图,所以最小生成树算法失效. 查资料后得知此类问题叫做最小树形图. 解决最小树形图问题的朱刘算法,算法核心基于找 [最小弧集->找环,消环缩点] 的思想,来慢慢构造树形图. 所有的灵魂都在这张图上.0.0 注意缩点后的弧权值的处理 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algo

poj3134 Command Network --- 最小树形图

新单词unidirectional get T T 求有向图上,以某点为根的,最小生成树 参考别人的模板 #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> #include<algorithm> #include<cmath> #define inf 2000000000 using namespac

poj 3164 Command Network(最小树形图模板)

Command Network http://poj.org/problem?id=3164 Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 18769   Accepted: 5392 Description After a long lasting war on words, a war on arms finally breaks out between littleken’s and KnuthOcean’s k

Poj 3164 Command Network【最小树形图】

Command Network Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 15914   Accepted: 4583 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 a