zoukankan      html  css  js  c++  java
  • 最小树形图:朱刘算法

    给一个有向图,求最小树形图的权值。

    用in存图,用pre记录前驱节点。

      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
    ",ans - sum, pos - m);
    112         puts("");
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    MKMapVIew学习系列2 在地图上绘制出你运行的轨迹
    WPF SDK研究 Intro(6) WordGame1
    WPF SDK研究 Intro(3) QuickStart3
    WPF SDK研究 Layout(1) Grid
    WPF SDK研究 目录 前言
    WPF SDK研究 Intro(7) WordGame2
    WPF SDK研究 Layout(2) GridComplex
    对vs2005创建的WPF模板分析
    WPF SDK研究 Intro(4) QuickStart4
    《Programming WPF》翻译 第6章 资源
  • 原文地址:https://www.cnblogs.com/St-Lovaer/p/12008216.html
Copyright © 2011-2022 走看看