• 最小树形图:朱刘算法


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

    用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 }
  • 相关阅读:
    DBCP,C3P0与Tomcat jdbc pool 连接池的比较
    MySQL:创建、修改和删除表
    MySQL添加用户、删除用户与授权
    王垠 :写给支持和反对《完全用Linux工作》的人们 ( 2004/8/26)
    王垠:完全用Linux工作 (2003)
    王垠:什么是“对用户友好”(2012/05/18)
    顿悟:Linux是拿来用的,不是拿来折腾的
    《从零开始搭建游戏服务器》MySQL安装配置
    ehcache 缓存
    servlet
  • 原文地址:https://www.cnblogs.com/St-Lovaer/p/12008216.html
Copyright © 2020-2023  润新知