无根最小树形图模板

  1 #include<iostream>
  2 using namespace std;
  3 #include<cstdio>
  4 #include<cstring>
  5 #define MAXN 1005
  6 #define INF 0x7f7f7f7f
  7 typedef __int64 type;
  8 struct node//边的权和顶点
  9 {
 10     int u, v;
 11     type w;
 12 }edge[MAXN * MAXN];
 13 int pre[MAXN], id[MAXN], vis[MAXN], n, m, pos;
 14 type in[MAXN];//存最小入边权,pre[v]为该边的起点
 15 type Directed_MST(int root, int V, int E)
 16 {
 17     type ret = 0;//存最小树形图总权值
 18     while(true)
 19     {
 20         int i;
 21         //1.找每个节点的最小入边
 22         for( i = 0; i < V; i++)
 23             in[i] = INF;//初始化为无穷大
 24         for( i = 0; i < E; i++)//遍历每条边
 25         {
 26             int u = edge[i].u;
 27             int v = edge[i].v;
 28             if(edge[i].w < in[v] && u != v)//说明顶点v有条权值较小的入边  记录之
 29             {
 30                 pre[v] = u;//节点u指向v
 31                 in[v] = edge[i].w;//最小入边
 32                 if(u == root)//这个点就是实际的起点
 33                     pos = i;
 34             }
 35         }
 36         for( i = 0; i < V; i++)//判断是否存在最小树形图
 37         {
 38             if(i == root)
 39                 continue;
 40             if(in[i] == INF)
 41                 return -1;//除了根以外有点没有入边,则根无法到达它  说明它是独立的点 一定不能构成树形图
 42         }
 43         //2.找环
 44         int cnt = 0;//记录环数
 45         memset(id, -1, sizeof(id));
 46         memset(vis, -1, sizeof(vis));
 47         in[root] = 0;
 48         for( i = 0; i < V; i++) //标记每个环
 49         {
 50             ret += in[i];//记录权值
 51             int v = i;
 52             while(vis[v] != i && id[v] == -1 && v != root)
 53             {
 54                 vis[v] = i;
 55                 v = pre[v];
 56             }
 57             if(v != root && id[v] == -1)
 58             {
 59                 for(int u = pre[v]; u != v; u = pre[u])
 60                     id[u] = cnt;//标记节点u为第几个环
 61                 id[v] = cnt++;
 62             }
 63         }
 64         if(cnt == 0)
 65             break; //无环   则break
 66         for( i = 0; i < V; i++)
 67             if(id[i] == -1)
 68                 id[i] = cnt++;
 69             //3.建立新图   缩点,重新标记
 70             for( i = 0; i < E; i++)
 71             {
 72                 int u = edge[i].u;
 73                 int v = edge[i].v;
 74                 edge[i].u = id[u];
 75                 edge[i].v = id[v];
 76                 if(id[u] != id[v])
 77                     edge[i].w -= in[v];
 78             }
 79             V = cnt;
 80             root = id[root];
 81     }
 82     return ret;
 83 }
 84 int main()
 85 {
 86     int i;
 87     while(scanf("%d%d", &n, &m) != EOF)
 88     {
 89         type sum = 0;
 90         for( i = 0; i < m; i++)
 91         {
 92             scanf("%d%d%I64d", &edge[i].u, &edge[i].v, &edge[i].w);
 93             edge[i].u++; edge[i].v++;
 94             sum += edge[i].w;
 95         }
 96       sum ++;
 97         for( i = m; i < m + n; i++)//增加超级节点0,节点0到其余各个节点的边权相同(此题中 边权要大于原图的总边权值)
 98         {
 99             edge[i].u = 0;
100             edge[i].v = i - m + 1;
101             edge[i].w = sum;
102         }
103         type ans = Directed_MST(0, n + 1, m + n);
104         //n+1为总结点数,m+n为总边数
105         //ans代表以超级节点0为根的最小树形图的总权值,
106         //将ans减去sum,如果差值小于sum,说明节点0的出度只有1,说明原图是连通图
107         //如果差值>=sum,那么说明节点0的出度不止为1,说明原图不是连通图
108         if(ans == -1 || ans - sum >= sum)
109             puts("impossible");
110         else
111             printf("%I64d %d\n",ans - sum, pos - m);
112         puts("");
113     }
114     return 0;
115 }

时间: 2024-10-28 19:12:58

无根最小树形图模板的相关文章

【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 最小树形图模板 (优先c++ ,g++ 有时会wa==)

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include <iostream> #define eps 1e-8 using namespace std; /* 最小树形图图模版-朱刘算法 模版说明:点标号必须0-(N-1) 必须去除到自身的点(到自身的边的边权赋无限大) */ #define M 109 #define type double

poj 3164 最小树形图模板!!!

/* tle十几次,最后发现当i从1开始时,给环赋值时要注意啊! 最小树形图 */ #include<stdio.h> #include<string.h> #include<math.h> #define N 110 #define inf 0x3fffffff #define eps 1e-10 struct node { int u,v; double w; }edge[N*N*2]; double distance (double x,double y,doub

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+=tem

最小树形图(模板)

本文链接:http://www.cnblogs.com/Ash-ly/p/5536796.html 定义: 设G = (V, E)是一个有向图,如果具有下述性质 (1)G中不包含有向环; (2)存在一个顶点vi,它不是任何弧的终点,而V的其它顶点都恰好是唯一的一条弧的终点.则称 G是以vi为根的树形图. 最小树形图就是有向图G = (V, E)中以vi为根的树形图中权值的和最小的那一个. 用朱刘算法求最小树形图: 最小树形图基于贪心和缩点的思想,所谓缩点,就是将几个点看成一个点,所有连到这几个点

poj3164最小树形图模板题

题目大意:给定一个有向图,根节点已知,求该有向图的最小树形图.最小树形图即有向图的最小生成树,定义为:选择一些边,使得根节点能够到达图中所有的节点,并使得选出的边的边权和最小. 题目算法:朱-刘算法(即由中国人朱永津和刘振宏共同发明的算法). 算法步骤如下: 1.判断图的连通性,若不连通直接无解,否则一定有解. 2.为除了根节点以外的所有点选择一个权值最小的入边,假设用pre数组记录前驱,f数组记录选择的边长,记所选边权和为temp. 3.(可利用并查集)判断选择的的边是否构成环,若没有则直接a

朱、刘算法:求最小树形图权值个人理解+个人详解【最小树形图模板】

什么是最小树形图?相信大家如果会过来看这篇文章,想必也应该对最小生成树有所了解的,最小生成树求的是无向图的一颗生成树的最小权值.我们的最小树形图就是来解决一个有向图的一颗生成树的最小权值,对于度娘来说,最小树形图是这样定义的:最小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T中所有边的总权值最小. 通解最小树形图的一种算法是是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法:朱.刘算法. 今天我们就来浅谈一下最小树形图的问题. 大题上完整的朱

最小树形图模板 UVA11183

题意:给定n个节点m条边的有向带权图,求以0为根节点的最小树形图权值大小 1 #include<cstdio> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 const int maxn=1e3+10; 6 const int maxm=4e4+10; 7 const int inf=0x3f3f3f3f; 8 int n,m; 9 int cost[maxn],pre[maxn]

hdoj 4009 Transfer water 【无源点最小树形图】【好题】

题目:hdoj 4009 Transfer water 题意:题目有点长,说是有个村子,有 n 户人家要用水,他们加的位置用三维坐标来表示(x,y,z),他们有两种选择: 1:自己挖一口井,花费为 z * cost_x 2:从别人家接个水管引过来,化为为距离 * cost_y,如果要引的地方比当前地方低的话,还要买一个水泵,花费cost_z. 距离算法|x2‐x1|+|y2‐y1|+|z2‐z1|. 然后求让所有的人都有用的水的最小花费. 分析:发现它是一个求最小生成树的题目,但是关键点有二 1